Commit 69e3948a authored by David S. Miller's avatar David S. Miller

Merge tag 'nfc-next-4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next

Samuel Ortiz says:

====================
NFC 4.12 pull request

This is the NFC pull request for 4.12. We have:

- Improvements for the pn533 command queue handling and device
  registration order.
- Removal of platform data for the pn544 and st21nfca drivers.
- Additional device tree options to support more trf7970a hardware options.
- Support for Sony's RC-S380P through the port100 driver.
- Removal of the obsolte nfcwilink driver.
- Headers inclusion cleanups (miscdevice.h, unaligned.h) for many drivers.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ea8ffc08 4ea20639
...@@ -5,8 +5,8 @@ Required properties: ...@@ -5,8 +5,8 @@ Required properties:
- spi-max-frequency: Maximum SPI frequency (<= 2000000). - spi-max-frequency: Maximum SPI frequency (<= 2000000).
- interrupt-parent: phandle of parent interrupt handler. - interrupt-parent: phandle of parent interrupt handler.
- interrupts: A single interrupt specifier. - interrupts: A single interrupt specifier.
- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the - ti,enable-gpios: One or two GPIO entries used for 'EN' and 'EN2' pins on the
TRF7970A. TRF7970A. EN2 is optional.
- vin-supply: Regulator for supply voltage to VIN pin - vin-supply: Regulator for supply voltage to VIN pin
Optional SoC Specific Properties: Optional SoC Specific Properties:
...@@ -21,6 +21,8 @@ Optional SoC Specific Properties: ...@@ -21,6 +21,8 @@ Optional SoC Specific Properties:
- t5t-rmb-extra-byte-quirk: Specify that the trf7970a has the 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 where an extra byte is returned by Read Multiple Block commands issued
to Type 5 tags. to Type 5 tags.
- vdd-io-supply: Regulator specifying voltage for vdd-io
- clock-frequency: Set to specify that the input frequency to the trf7970a is 13560000Hz or 27120000Hz
Example (for ARM-based BeagleBone with TRF7970A on SPI1): Example (for ARM-based BeagleBone with TRF7970A on SPI1):
...@@ -39,10 +41,12 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1): ...@@ -39,10 +41,12 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1):
<&gpio2 5 GPIO_ACTIVE_LOW>; <&gpio2 5 GPIO_ACTIVE_LOW>;
vin-supply = <&ldo3_reg>; vin-supply = <&ldo3_reg>;
vin-voltage-override = <5000000>; vin-voltage-override = <5000000>;
vdd-io-supply = <&ldo2_reg>;
autosuspend-delay = <30000>; autosuspend-delay = <30000>;
irq-status-read-quirk; irq-status-read-quirk;
en2-rf-quirk; en2-rf-quirk;
t5t-rmb-extra-byte-quirk; t5t-rmb-extra-byte-quirk;
clock-frequency = <27120000>;
status = "okay"; status = "okay";
}; };
}; };
...@@ -8876,8 +8876,6 @@ S: Supported ...@@ -8876,8 +8876,6 @@ S: Supported
F: drivers/net/ethernet/qlogic/netxen/ F: drivers/net/ethernet/qlogic/netxen/
NFC SUBSYSTEM NFC SUBSYSTEM
M: Lauro Ramos Venancio <lauro.venancio@openbossa.org>
M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
M: Samuel Ortiz <sameo@linux.intel.com> M: Samuel Ortiz <sameo@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: linux-nfc@lists.01.org (subscribers-only) L: linux-nfc@lists.01.org (subscribers-only)
......
...@@ -5,17 +5,6 @@ ...@@ -5,17 +5,6 @@
menu "Near Field Communication (NFC) devices" menu "Near Field Communication (NFC) devices"
depends on NFC depends on NFC
config NFC_WILINK
tristate "Texas Instruments NFC WiLink driver"
depends on TI_ST && NFC_NCI
help
This enables the NFC driver for Texas Instrument's BT/FM/GPS/NFC
combo devices. This makes use of shared transport line discipline
core driver to communicate with the NFC core of the combo chip.
Say Y here to compile support for Texas Instrument's NFC WiLink driver
into the kernel or say M to compile it as module.
config NFC_TRF7970A config NFC_TRF7970A
tristate "Texas Instruments TRF7970a NFC driver" tristate "Texas Instruments TRF7970a NFC driver"
depends on SPI && NFC_DIGITAL depends on SPI && NFC_DIGITAL
......
...@@ -6,7 +6,6 @@ obj-$(CONFIG_NFC_FDP) += fdp/ ...@@ -6,7 +6,6 @@ obj-$(CONFIG_NFC_FDP) += fdp/
obj-$(CONFIG_NFC_PN544) += pn544/ obj-$(CONFIG_NFC_PN544) += pn544/
obj-$(CONFIG_NFC_MICROREAD) += microread/ obj-$(CONFIG_NFC_MICROREAD) += microread/
obj-$(CONFIG_NFC_PN533) += pn533/ obj-$(CONFIG_NFC_PN533) += pn533/
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o
obj-$(CONFIG_NFC_SIM) += nfcsim.o obj-$(CONFIG_NFC_SIM) += nfcsim.o
obj-$(CONFIG_NFC_PORT100) += port100.o obj-$(CONFIG_NFC_PORT100) += port100.o
......
...@@ -210,14 +210,14 @@ static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id) ...@@ -210,14 +210,14 @@ static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
struct sk_buff *skb; struct sk_buff *skb;
int r; int r;
client = phy->i2c_dev;
dev_dbg(&client->dev, "%s\n", __func__);
if (!phy || irq != phy->i2c_dev->irq) { if (!phy || irq != phy->i2c_dev->irq) {
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return IRQ_NONE; return IRQ_NONE;
} }
client = phy->i2c_dev;
dev_dbg(&client->dev, "%s\n", __func__);
r = fdp_nci_i2c_read(phy, &skb); r = fdp_nci_i2c_read(phy, &skb);
if (r == -EREMOTEIO) if (r == -EREMOTEIO)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/unaligned/access_ok.h> #include <asm/unaligned.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <net/nfc/nci.h> #include <net/nfc/nci.h>
...@@ -281,12 +281,11 @@ static int process_state_fw_dnld(struct nfcmrvl_private *priv, ...@@ -281,12 +281,11 @@ static int process_state_fw_dnld(struct nfcmrvl_private *priv,
return -EINVAL; return -EINVAL;
} }
skb_pull(skb, 1); skb_pull(skb, 1);
memcpy(&len, skb->data, 2); len = get_unaligned_le16(skb->data);
skb_pull(skb, 2); skb_pull(skb, 2);
comp_len = get_unaligned_le16(skb->data);
memcpy(&comp_len, skb->data, 2); memcpy(&comp_len, skb->data, 2);
skb_pull(skb, 2); skb_pull(skb, 2);
len = get_unaligned_le16(&len);
comp_len = get_unaligned_le16(&comp_len);
if (((~len) & 0xFFFF) != comp_len) { if (((~len) & 0xFFFF) != comp_len) {
nfc_err(priv->dev, "bad len complement: %x %x %x", nfc_err(priv->dev, "bad len complement: %x %x %x",
len, comp_len, (~len & 0xFFFF)); len, comp_len, (~len & 0xFFFF));
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <net/nfc/nci.h> #include <net/nfc/nci.h>
#include <net/nfc/nci_core.h> #include <net/nfc/nci_core.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h>
#include "nfcmrvl.h" #include "nfcmrvl.h"
#define SPI_WAIT_HANDSHAKE 1 #define SPI_WAIT_HANDSHAKE 1
...@@ -96,10 +95,9 @@ static int nfcmrvl_spi_nci_send(struct nfcmrvl_private *priv, ...@@ -96,10 +95,9 @@ static int nfcmrvl_spi_nci_send(struct nfcmrvl_private *priv,
/* Send the SPI packet */ /* Send the SPI packet */
err = nci_spi_send(drv_data->nci_spi, &drv_data->handshake_completion, err = nci_spi_send(drv_data->nci_spi, &drv_data->handshake_completion,
skb); skb);
if (err != 0) { if (err)
nfc_err(priv->dev, "spi_send failed %d", err); nfc_err(priv->dev, "spi_send failed %d", err);
kfree_skb(skb);
}
return err; return err;
} }
......
/*
* Texas Instrument's NFC Driver For Shared Transport.
*
* NFC Driver acts as interface between NCI core and
* TI Shared Transport Layer.
*
* Copyright (C) 2011 Texas Instruments, Inc.
*
* Written by Ilan Elias <ilane@ti.com>
*
* Acknowledgements:
* This file is based on btwilink.c, which was written
* by Raja Mani and Pavan Savoy.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms 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/platform_device.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/firmware.h>
#include <linux/nfc.h>
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
#include <linux/ti_wilink_st.h>
#define NFCWILINK_CHNL 12
#define NFCWILINK_OPCODE 7
#define NFCWILINK_MAX_FRAME_SIZE 300
#define NFCWILINK_HDR_LEN 4
#define NFCWILINK_OFFSET_LEN_IN_HDR 1
#define NFCWILINK_LEN_SIZE 2
#define NFCWILINK_REGISTER_TIMEOUT 8000 /* 8 sec */
#define NFCWILINK_CMD_TIMEOUT 5000 /* 5 sec */
#define BTS_FILE_NAME_MAX_SIZE 40
#define BTS_FILE_HDR_MAGIC 0x42535442
#define BTS_FILE_CMD_MAX_LEN 0xff
#define BTS_FILE_ACTION_TYPE_SEND_CMD 1
#define NCI_VS_NFCC_INFO_CMD_GID 0x2f
#define NCI_VS_NFCC_INFO_CMD_OID 0x12
#define NCI_VS_NFCC_INFO_RSP_GID 0x4f
#define NCI_VS_NFCC_INFO_RSP_OID 0x12
struct nfcwilink_hdr {
__u8 chnl;
__u8 opcode;
__le16 len;
} __packed;
struct nci_vs_nfcc_info_cmd {
__u8 gid;
__u8 oid;
__u8 plen;
} __packed;
struct nci_vs_nfcc_info_rsp {
__u8 gid;
__u8 oid;
__u8 plen;
__u8 status;
__u8 hw_id;
__u8 sw_ver_x;
__u8 sw_ver_z;
__u8 patch_id;
} __packed;
struct bts_file_hdr {
__le32 magic;
__le32 ver;
__u8 rfu[24];
__u8 actions[0];
} __packed;
struct bts_file_action {
__le16 type;
__le16 len;
__u8 data[0];
} __packed;
struct nfcwilink {
struct platform_device *pdev;
struct nci_dev *ndev;
unsigned long flags;
int st_register_cb_status;
long (*st_write) (struct sk_buff *);
struct completion completed;
struct nci_vs_nfcc_info_rsp nfcc_info;
};
/* NFCWILINK driver flags */
enum {
NFCWILINK_RUNNING,
NFCWILINK_FW_DOWNLOAD,
};
static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb);
static inline struct sk_buff *nfcwilink_skb_alloc(unsigned int len, gfp_t how)
{
struct sk_buff *skb;
skb = alloc_skb(len + NFCWILINK_HDR_LEN, how);
if (skb)
skb_reserve(skb, NFCWILINK_HDR_LEN);
return skb;
}
static void nfcwilink_fw_download_receive(struct nfcwilink *drv,
struct sk_buff *skb)
{
struct nci_vs_nfcc_info_rsp *rsp = (void *)skb->data;
/* Detect NCI_VS_NFCC_INFO_RSP and store the result */
if ((skb->len > 3) && (rsp->gid == NCI_VS_NFCC_INFO_RSP_GID) &&
(rsp->oid == NCI_VS_NFCC_INFO_RSP_OID)) {
memcpy(&drv->nfcc_info, rsp,
sizeof(struct nci_vs_nfcc_info_rsp));
}
kfree_skb(skb);
complete(&drv->completed);
}
static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name)
{
struct nci_vs_nfcc_info_cmd *cmd;
struct sk_buff *skb;
unsigned long comp_ret;
int rc;
skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd),
GFP_KERNEL);
if (!skb) {
nfc_err(&drv->pdev->dev,
"no memory for nci_vs_nfcc_info_cmd\n");
return -ENOMEM;
}
cmd = (struct nci_vs_nfcc_info_cmd *)
skb_put(skb, sizeof(struct nci_vs_nfcc_info_cmd));
cmd->gid = NCI_VS_NFCC_INFO_CMD_GID;
cmd->oid = NCI_VS_NFCC_INFO_CMD_OID;
cmd->plen = 0;
drv->nfcc_info.plen = 0;
rc = nfcwilink_send(drv->ndev, skb);
if (rc)
return rc;
comp_ret = wait_for_completion_timeout(&drv->completed,
msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT));
dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n",
comp_ret);
if (comp_ret == 0) {
nfc_err(&drv->pdev->dev,
"timeout on wait_for_completion_timeout\n");
return -ETIMEDOUT;
}
dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d\n",
drv->nfcc_info.plen, drv->nfcc_info.status);
if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) {
nfc_err(&drv->pdev->dev, "invalid nci_vs_nfcc_info_rsp\n");
return -EINVAL;
}
snprintf(file_name, BTS_FILE_NAME_MAX_SIZE,
"TINfcInit_%d.%d.%d.%d.bts",
drv->nfcc_info.hw_id,
drv->nfcc_info.sw_ver_x,
drv->nfcc_info.sw_ver_z,
drv->nfcc_info.patch_id);
nfc_info(&drv->pdev->dev, "nfcwilink FW file name: %s\n", file_name);
return 0;
}
static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len)
{
struct nfcwilink_hdr *hdr = (struct nfcwilink_hdr *)data;
struct sk_buff *skb;
unsigned long comp_ret;
int rc;
/* verify valid cmd for the NFC channel */
if ((len <= sizeof(struct nfcwilink_hdr)) ||
(len > BTS_FILE_CMD_MAX_LEN) ||
(hdr->chnl != NFCWILINK_CHNL) ||
(hdr->opcode != NFCWILINK_OPCODE)) {
nfc_err(&drv->pdev->dev,
"ignoring invalid bts cmd, len %d, chnl %d, opcode %d\n",
len, hdr->chnl, hdr->opcode);
return 0;
}
/* remove the ST header */
len -= sizeof(struct nfcwilink_hdr);
data += sizeof(struct nfcwilink_hdr);
skb = nfcwilink_skb_alloc(len, GFP_KERNEL);
if (!skb) {
nfc_err(&drv->pdev->dev, "no memory for bts cmd\n");
return -ENOMEM;
}
memcpy(skb_put(skb, len), data, len);
rc = nfcwilink_send(drv->ndev, skb);
if (rc)
return rc;
comp_ret = wait_for_completion_timeout(&drv->completed,
msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT));
dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld\n",
comp_ret);
if (comp_ret == 0) {
nfc_err(&drv->pdev->dev,
"timeout on wait_for_completion_timeout\n");
return -ETIMEDOUT;
}
return 0;
}
static int nfcwilink_download_fw(struct nfcwilink *drv)
{
unsigned char file_name[BTS_FILE_NAME_MAX_SIZE];
const struct firmware *fw;
__u16 action_type, action_len;
__u8 *ptr;
int len, rc;
set_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags);
rc = nfcwilink_get_bts_file_name(drv, file_name);
if (rc)
goto exit;
rc = request_firmware(&fw, file_name, &drv->pdev->dev);
if (rc) {
nfc_err(&drv->pdev->dev, "request_firmware failed %d\n", rc);
/* if the file is not found, don't exit with failure */
if (rc == -ENOENT)
rc = 0;
goto exit;
}
len = fw->size;
ptr = (__u8 *)fw->data;
if ((len == 0) || (ptr == NULL)) {
dev_dbg(&drv->pdev->dev,
"request_firmware returned size %d\n", len);
goto release_fw;
}
if (__le32_to_cpu(((struct bts_file_hdr *)ptr)->magic) !=
BTS_FILE_HDR_MAGIC) {
nfc_err(&drv->pdev->dev, "wrong bts magic number\n");
rc = -EINVAL;
goto release_fw;
}
/* remove the BTS header */
len -= sizeof(struct bts_file_hdr);
ptr += sizeof(struct bts_file_hdr);
while (len > 0) {
action_type =
__le16_to_cpu(((struct bts_file_action *)ptr)->type);
action_len =
__le16_to_cpu(((struct bts_file_action *)ptr)->len);
dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d\n",
action_type, action_len);
switch (action_type) {
case BTS_FILE_ACTION_TYPE_SEND_CMD:
rc = nfcwilink_send_bts_cmd(drv,
((struct bts_file_action *)ptr)->data,
action_len);
if (rc)
goto release_fw;
break;
}
/* advance to the next action */
len -= (sizeof(struct bts_file_action) + action_len);
ptr += (sizeof(struct bts_file_action) + action_len);
}
release_fw:
release_firmware(fw);
exit:
clear_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags);
return rc;
}
/* Called by ST when registration is complete */
static void nfcwilink_register_complete(void *priv_data, int data)
{
struct nfcwilink *drv = priv_data;
/* store ST registration status */
drv->st_register_cb_status = data;
/* complete the wait in nfc_st_open() */
complete(&drv->completed);
}
/* Called by ST when receive data is available */
static long nfcwilink_receive(void *priv_data, struct sk_buff *skb)
{
struct nfcwilink *drv = priv_data;
int rc;
if (!skb)
return -EFAULT;
if (!drv) {
kfree_skb(skb);
return -EFAULT;
}
dev_dbg(&drv->pdev->dev, "receive entry, len %d\n", skb->len);
/* strip the ST header
(apart for the chnl byte, which is not received in the hdr) */
skb_pull(skb, (NFCWILINK_HDR_LEN-1));
if (test_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags)) {
nfcwilink_fw_download_receive(drv, skb);
return 0;
}
/* Forward skb to NCI core layer */
rc = nci_recv_frame(drv->ndev, skb);
if (rc < 0) {
nfc_err(&drv->pdev->dev, "nci_recv_frame failed %d\n", rc);
return rc;
}
return 0;
}
/* protocol structure registered with ST */
static struct st_proto_s nfcwilink_proto = {
.chnl_id = NFCWILINK_CHNL,
.max_frame_size = NFCWILINK_MAX_FRAME_SIZE,
.hdr_len = (NFCWILINK_HDR_LEN-1), /* not including chnl byte */
.offset_len_in_hdr = NFCWILINK_OFFSET_LEN_IN_HDR,
.len_size = NFCWILINK_LEN_SIZE,
.reserve = 0,
.recv = nfcwilink_receive,
.reg_complete_cb = nfcwilink_register_complete,
.write = NULL,
};
static int nfcwilink_open(struct nci_dev *ndev)
{
struct nfcwilink *drv = nci_get_drvdata(ndev);
unsigned long comp_ret;
int rc;
if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) {
rc = -EBUSY;
goto exit;
}
nfcwilink_proto.priv_data = drv;
init_completion(&drv->completed);
drv->st_register_cb_status = -EINPROGRESS;
rc = st_register(&nfcwilink_proto);
if (rc < 0) {
if (rc == -EINPROGRESS) {
comp_ret = wait_for_completion_timeout(
&drv->completed,
msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT));
dev_dbg(&drv->pdev->dev,
"wait_for_completion_timeout returned %ld\n",
comp_ret);
if (comp_ret == 0) {
/* timeout */
rc = -ETIMEDOUT;
goto clear_exit;
} else if (drv->st_register_cb_status != 0) {
rc = drv->st_register_cb_status;
nfc_err(&drv->pdev->dev,
"st_register_cb failed %d\n", rc);
goto clear_exit;
}
} else {
nfc_err(&drv->pdev->dev, "st_register failed %d\n", rc);
goto clear_exit;
}
}
/* st_register MUST fill the write callback */
BUG_ON(nfcwilink_proto.write == NULL);
drv->st_write = nfcwilink_proto.write;
if (nfcwilink_download_fw(drv)) {
nfc_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d\n",
rc);
/* open should succeed, even if the FW download failed */
}
goto exit;
clear_exit:
clear_bit(NFCWILINK_RUNNING, &drv->flags);
exit:
return rc;
}
static int nfcwilink_close(struct nci_dev *ndev)
{
struct nfcwilink *drv = nci_get_drvdata(ndev);
int rc;
if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags))
return 0;
rc = st_unregister(&nfcwilink_proto);
if (rc)
nfc_err(&drv->pdev->dev, "st_unregister failed %d\n", rc);
drv->st_write = NULL;
return rc;
}
static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb)
{
struct nfcwilink *drv = nci_get_drvdata(ndev);
struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000};
long len;
dev_dbg(&drv->pdev->dev, "send entry, len %d\n", skb->len);
if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) {
kfree_skb(skb);
return -EINVAL;
}
/* add the ST hdr to the start of the buffer */
hdr.len = cpu_to_le16(skb->len);
memcpy(skb_push(skb, NFCWILINK_HDR_LEN), &hdr, NFCWILINK_HDR_LEN);
/* Insert skb to shared transport layer's transmit queue.
* Freeing skb memory is taken care in shared transport layer,
* so don't free skb memory here.
*/
len = drv->st_write(skb);
if (len < 0) {
kfree_skb(skb);
nfc_err(&drv->pdev->dev, "st_write failed %ld\n", len);
return -EFAULT;
}
return 0;
}
static struct nci_ops nfcwilink_ops = {
.open = nfcwilink_open,
.close = nfcwilink_close,
.send = nfcwilink_send,
};
static int nfcwilink_probe(struct platform_device *pdev)
{
struct nfcwilink *drv;
int rc;
__u32 protocols;
drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL);
if (!drv) {
rc = -ENOMEM;
goto exit;
}
drv->pdev = pdev;
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;
drv->ndev = nci_allocate_device(&nfcwilink_ops,
protocols,
NFCWILINK_HDR_LEN,
0);
if (!drv->ndev) {
nfc_err(&pdev->dev, "nci_allocate_device failed\n");
rc = -ENOMEM;
goto exit;
}
nci_set_parent_dev(drv->ndev, &pdev->dev);
nci_set_drvdata(drv->ndev, drv);
rc = nci_register_device(drv->ndev);
if (rc < 0) {
nfc_err(&pdev->dev, "nci_register_device failed %d\n", rc);
goto free_dev_exit;
}
dev_set_drvdata(&pdev->dev, drv);
goto exit;
free_dev_exit:
nci_free_device(drv->ndev);
exit:
return rc;
}
static int nfcwilink_remove(struct platform_device *pdev)
{
struct nfcwilink *drv = dev_get_drvdata(&pdev->dev);
struct nci_dev *ndev;
if (!drv)
return -EFAULT;
ndev = drv->ndev;
nci_unregister_device(ndev);
nci_free_device(ndev);
return 0;
}
static struct platform_driver nfcwilink_driver = {
.probe = nfcwilink_probe,
.remove = nfcwilink_remove,
.driver = {
.name = "nfcwilink",
},
};
module_platform_driver(nfcwilink_driver);
/* ------ Module Info ------ */
MODULE_AUTHOR("Ilan Elias <ilane@ti.com>");
MODULE_DESCRIPTION("NFC Driver for TI Shared Transport");
MODULE_LICENSE("GPL");
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <linux/unaligned/access_ok.h> #include <asm/unaligned.h>
#include "nxp-nci.h" #include "nxp-nci.h"
......
...@@ -29,14 +29,13 @@ ...@@ -29,14 +29,13 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/platform_data/nxp-nci.h> #include <linux/platform_data/nxp-nci.h>
#include <linux/unaligned/access_ok.h> #include <asm/unaligned.h>
#include <net/nfc/nfc.h> #include <net/nfc/nfc.h>
...@@ -86,7 +85,7 @@ static int nxp_nci_i2c_write(void *phy_id, struct sk_buff *skb) ...@@ -86,7 +85,7 @@ static int nxp_nci_i2c_write(void *phy_id, struct sk_buff *skb)
r = i2c_master_send(client, skb->data, skb->len); r = i2c_master_send(client, skb->data, skb->len);
if (r < 0) { if (r < 0) {
/* Retry, chip was in standby */ /* Retry, chip was in standby */
usleep_range(110000, 120000); msleep(110);
r = i2c_master_send(client, skb->data, skb->len); r = i2c_master_send(client, skb->data, skb->len);
} }
...@@ -127,7 +126,7 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy, ...@@ -127,7 +126,7 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
goto fw_read_exit; goto fw_read_exit;
} }
frame_len = (get_unaligned_be16(&header) & NXP_NCI_FW_FRAME_LEN_MASK) + frame_len = (be16_to_cpu(header) & NXP_NCI_FW_FRAME_LEN_MASK) +
NXP_NCI_FW_CRC_LEN; NXP_NCI_FW_CRC_LEN;
*skb = alloc_skb(NXP_NCI_FW_HDR_LEN + frame_len, GFP_KERNEL); *skb = alloc_skb(NXP_NCI_FW_HDR_LEN + frame_len, GFP_KERNEL);
......
...@@ -51,7 +51,7 @@ static int pn533_i2c_send_ack(struct pn533 *dev, gfp_t flags) ...@@ -51,7 +51,7 @@ static int pn533_i2c_send_ack(struct pn533 *dev, gfp_t flags)
{ {
struct pn533_i2c_phy *phy = dev->phy; struct pn533_i2c_phy *phy = dev->phy;
struct i2c_client *client = phy->i2c_dev; struct i2c_client *client = phy->i2c_dev;
u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
/* spec 6.2.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ /* spec 6.2.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
int rc; int rc;
...@@ -206,14 +206,6 @@ static int pn533_i2c_probe(struct i2c_client *client, ...@@ -206,14 +206,6 @@ static int pn533_i2c_probe(struct i2c_client *client,
phy->i2c_dev = client; phy->i2c_dev = client;
i2c_set_clientdata(client, phy); i2c_set_clientdata(client, phy);
r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn,
IRQF_TRIGGER_FALLING |
IRQF_SHARED | IRQF_ONESHOT,
PN533_I2C_DRIVER_NAME, phy);
if (r < 0)
nfc_err(&client->dev, "Unable to register IRQ handler\n");
priv = pn533_register_device(PN533_DEVICE_PN532, priv = pn533_register_device(PN533_DEVICE_PN532,
PN533_NO_TYPE_B_PROTOCOLS, PN533_NO_TYPE_B_PROTOCOLS,
PN533_PROTO_REQ_ACK_RESP, PN533_PROTO_REQ_ACK_RESP,
...@@ -223,16 +215,32 @@ static int pn533_i2c_probe(struct i2c_client *client, ...@@ -223,16 +215,32 @@ static int pn533_i2c_probe(struct i2c_client *client,
if (IS_ERR(priv)) { if (IS_ERR(priv)) {
r = PTR_ERR(priv); r = PTR_ERR(priv);
goto err_register; return r;
} }
phy->priv = priv; phy->priv = priv;
r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn,
IRQF_TRIGGER_FALLING |
IRQF_SHARED | IRQF_ONESHOT,
PN533_I2C_DRIVER_NAME, phy);
if (r < 0) {
nfc_err(&client->dev, "Unable to register IRQ handler\n");
goto irq_rqst_err;
}
r = pn533_finalize_setup(priv);
if (r)
goto fn_setup_err;
return 0; return 0;
err_register: fn_setup_err:
free_irq(client->irq, phy); free_irq(client->irq, phy);
irq_rqst_err:
pn533_unregister_device(phy->priv);
return r; return r;
} }
...@@ -242,10 +250,10 @@ static int pn533_i2c_remove(struct i2c_client *client) ...@@ -242,10 +250,10 @@ static int pn533_i2c_remove(struct i2c_client *client)
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
pn533_unregister_device(phy->priv);
free_irq(client->irq, phy); free_irq(client->irq, phy);
pn533_unregister_device(phy->priv);
return 0; return 0;
} }
......
...@@ -383,14 +383,18 @@ static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code, ...@@ -383,14 +383,18 @@ static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code,
static int pn533_send_async_complete(struct pn533 *dev) static int pn533_send_async_complete(struct pn533 *dev)
{ {
struct pn533_cmd *cmd = dev->cmd; struct pn533_cmd *cmd = dev->cmd;
int status = cmd->status; struct sk_buff *resp;
int status, rc = 0;
struct sk_buff *req = cmd->req; if (!cmd) {
struct sk_buff *resp = cmd->resp; dev_dbg(dev->dev, "%s: cmd not set\n", __func__);
goto done;
}
int rc; dev_kfree_skb(cmd->req);
dev_kfree_skb(req); status = cmd->status;
resp = cmd->resp;
if (status < 0) { if (status < 0) {
rc = cmd->complete_cb(dev, cmd->complete_cb_context, rc = cmd->complete_cb(dev, cmd->complete_cb_context,
...@@ -399,8 +403,14 @@ static int pn533_send_async_complete(struct pn533 *dev) ...@@ -399,8 +403,14 @@ static int pn533_send_async_complete(struct pn533 *dev)
goto done; goto done;
} }
skb_pull(resp, dev->ops->rx_header_len); /* when no response is set we got interrupted */
skb_trim(resp, resp->len - dev->ops->rx_tail_len); if (!resp)
resp = ERR_PTR(-EINTR);
if (!IS_ERR(resp)) {
skb_pull(resp, dev->ops->rx_header_len);
skb_trim(resp, resp->len - dev->ops->rx_tail_len);
}
rc = cmd->complete_cb(dev, cmd->complete_cb_context, resp); rc = cmd->complete_cb(dev, cmd->complete_cb_context, resp);
...@@ -434,12 +444,14 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, ...@@ -434,12 +444,14 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
mutex_lock(&dev->cmd_lock); mutex_lock(&dev->cmd_lock);
if (!dev->cmd_pending) { if (!dev->cmd_pending) {
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req); rc = dev->phy_ops->send_frame(dev, req);
if (rc) if (rc) {
dev->cmd = NULL;
goto error; goto error;
}
dev->cmd_pending = 1; dev->cmd_pending = 1;
dev->cmd = cmd;
goto unlock; goto unlock;
} }
...@@ -511,11 +523,12 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, ...@@ -511,11 +523,12 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
pn533_build_cmd_frame(dev, cmd_code, req); pn533_build_cmd_frame(dev, cmd_code, req);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req); rc = dev->phy_ops->send_frame(dev, req);
if (rc < 0) if (rc < 0) {
dev->cmd = NULL;
kfree(cmd); kfree(cmd);
else }
dev->cmd = cmd;
return rc; return rc;
} }
...@@ -550,14 +563,15 @@ static void pn533_wq_cmd(struct work_struct *work) ...@@ -550,14 +563,15 @@ static void pn533_wq_cmd(struct work_struct *work)
mutex_unlock(&dev->cmd_lock); mutex_unlock(&dev->cmd_lock);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, cmd->req); rc = dev->phy_ops->send_frame(dev, cmd->req);
if (rc < 0) { if (rc < 0) {
dev->cmd = NULL;
dev_kfree_skb(cmd->req); dev_kfree_skb(cmd->req);
kfree(cmd); kfree(cmd);
return; return;
} }
dev->cmd = cmd;
} }
struct pn533_sync_cmd_response { struct pn533_sync_cmd_response {
...@@ -2556,6 +2570,31 @@ static int pn533_setup(struct pn533 *dev) ...@@ -2556,6 +2570,31 @@ static int pn533_setup(struct pn533 *dev)
return 0; return 0;
} }
int pn533_finalize_setup(struct pn533 *dev)
{
struct pn533_fw_version fw_ver;
int rc;
memset(&fw_ver, 0, sizeof(fw_ver));
rc = pn533_get_firmware_version(dev, &fw_ver);
if (rc) {
nfc_err(dev->dev, "Unable to get FW version\n");
return rc;
}
nfc_info(dev->dev, "NXP PN5%02X firmware ver %d.%d now attached\n",
fw_ver.ic, fw_ver.ver, fw_ver.rev);
rc = pn533_setup(dev);
if (rc)
return rc;
return 0;
}
EXPORT_SYMBOL_GPL(pn533_finalize_setup);
struct pn533 *pn533_register_device(u32 device_type, struct pn533 *pn533_register_device(u32 device_type,
u32 protocols, u32 protocols,
enum pn533_protocol_type protocol_type, enum pn533_protocol_type protocol_type,
...@@ -2565,7 +2604,6 @@ struct pn533 *pn533_register_device(u32 device_type, ...@@ -2565,7 +2604,6 @@ struct pn533 *pn533_register_device(u32 device_type,
struct device *dev, struct device *dev,
struct device *parent) struct device *parent)
{ {
struct pn533_fw_version fw_ver;
struct pn533 *priv; struct pn533 *priv;
int rc = -ENOMEM; int rc = -ENOMEM;
...@@ -2608,15 +2646,6 @@ struct pn533 *pn533_register_device(u32 device_type, ...@@ -2608,15 +2646,6 @@ struct pn533 *pn533_register_device(u32 device_type,
INIT_LIST_HEAD(&priv->cmd_queue); INIT_LIST_HEAD(&priv->cmd_queue);
memset(&fw_ver, 0, sizeof(fw_ver));
rc = pn533_get_firmware_version(priv, &fw_ver);
if (rc < 0)
goto destroy_wq;
nfc_info(dev, "NXP PN5%02X firmware ver %d.%d now attached\n",
fw_ver.ic, fw_ver.ver, fw_ver.rev);
priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
priv->ops->tx_header_len + priv->ops->tx_header_len +
PN533_CMD_DATAEXCH_HEAD_LEN, PN533_CMD_DATAEXCH_HEAD_LEN,
...@@ -2633,15 +2662,8 @@ struct pn533 *pn533_register_device(u32 device_type, ...@@ -2633,15 +2662,8 @@ struct pn533 *pn533_register_device(u32 device_type,
if (rc) if (rc)
goto free_nfc_dev; goto free_nfc_dev;
rc = pn533_setup(priv);
if (rc)
goto unregister_nfc_dev;
return priv; return priv;
unregister_nfc_dev:
nfc_unregister_device(priv->nfc_dev);
free_nfc_dev: free_nfc_dev:
nfc_free_device(priv->nfc_dev); nfc_free_device(priv->nfc_dev);
......
...@@ -231,6 +231,7 @@ struct pn533 *pn533_register_device(u32 device_type, ...@@ -231,6 +231,7 @@ struct pn533 *pn533_register_device(u32 device_type,
struct device *dev, struct device *dev,
struct device *parent); struct device *parent);
int pn533_finalize_setup(struct pn533 *dev);
void pn533_unregister_device(struct pn533 *priv); void pn533_unregister_device(struct pn533 *priv);
void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status); void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status);
......
...@@ -148,11 +148,11 @@ static int pn533_submit_urb_for_ack(struct pn533_usb_phy *phy, gfp_t flags) ...@@ -148,11 +148,11 @@ static int pn533_submit_urb_for_ack(struct pn533_usb_phy *phy, gfp_t flags)
static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags) static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
{ {
struct pn533_usb_phy *phy = dev->phy; struct pn533_usb_phy *phy = dev->phy;
u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
int rc; int rc;
phy->out_urb->transfer_buffer = ack; phy->out_urb->transfer_buffer = (u8 *)ack;
phy->out_urb->transfer_buffer_length = sizeof(ack); phy->out_urb->transfer_buffer_length = sizeof(ack);
rc = usb_submit_urb(phy->out_urb, flags); rc = usb_submit_urb(phy->out_urb, flags);
...@@ -543,6 +543,10 @@ static int pn533_usb_probe(struct usb_interface *interface, ...@@ -543,6 +543,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
phy->priv = priv; phy->priv = priv;
rc = pn533_finalize_setup(priv);
if (rc)
goto error;
usb_set_intfdata(interface, phy); usb_set_intfdata(interface, phy);
return 0; return 0;
......
...@@ -21,17 +21,13 @@ ...@@ -21,17 +21,13 @@
#include <linux/crc-ccitt.h> #include <linux/crc-ccitt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/platform_data/pn544.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/nfc/hci.h> #include <net/nfc/hci.h>
...@@ -165,8 +161,9 @@ struct pn544_i2c_phy { ...@@ -165,8 +161,9 @@ struct pn544_i2c_phy {
struct i2c_client *i2c_dev; struct i2c_client *i2c_dev;
struct nfc_hci_dev *hdev; struct nfc_hci_dev *hdev;
unsigned int gpio_en; struct gpio_desc *gpiod_en;
unsigned int gpio_fw; struct gpio_desc *gpiod_fw;
unsigned int en_polarity; unsigned int en_polarity;
u8 hw_variant; u8 hw_variant;
...@@ -208,19 +205,18 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) ...@@ -208,19 +205,18 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy)
nfc_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); nfc_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n");
/* Disable fw download */ /* Disable fw download */
gpio_set_value_cansleep(phy->gpio_fw, 0); gpiod_set_value_cansleep(phy->gpiod_fw, 0);
for (polarity = 0; polarity < 2; polarity++) { for (polarity = 0; polarity < 2; polarity++) {
phy->en_polarity = polarity; phy->en_polarity = polarity;
retry = 3; retry = 3;
while (retry--) { while (retry--) {
/* power off */ /* power off */
gpio_set_value_cansleep(phy->gpio_en, gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
!phy->en_polarity);
usleep_range(10000, 15000); usleep_range(10000, 15000);
/* power on */ /* power on */
gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity); gpiod_set_value_cansleep(phy->gpiod_en, phy->en_polarity);
usleep_range(10000, 15000); usleep_range(10000, 15000);
/* send reset */ /* send reset */
...@@ -239,14 +235,13 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) ...@@ -239,14 +235,13 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy)
"Could not detect nfc_en polarity, fallback to active high\n"); "Could not detect nfc_en polarity, fallback to active high\n");
out: out:
gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
} }
static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode) static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode)
{ {
gpio_set_value_cansleep(phy->gpio_fw, gpiod_set_value_cansleep(phy->gpiod_fw, run_mode == PN544_FW_MODE ? 1 : 0);
run_mode == PN544_FW_MODE ? 1 : 0); gpiod_set_value_cansleep(phy->gpiod_en, phy->en_polarity);
gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity);
usleep_range(10000, 15000); usleep_range(10000, 15000);
phy->run_mode = run_mode; phy->run_mode = run_mode;
...@@ -269,14 +264,14 @@ static void pn544_hci_i2c_disable(void *phy_id) ...@@ -269,14 +264,14 @@ static void pn544_hci_i2c_disable(void *phy_id)
{ {
struct pn544_i2c_phy *phy = phy_id; struct pn544_i2c_phy *phy = phy_id;
gpio_set_value_cansleep(phy->gpio_fw, 0); gpiod_set_value_cansleep(phy->gpiod_fw, 0);
gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
usleep_range(10000, 15000); usleep_range(10000, 15000);
gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity); gpiod_set_value_cansleep(phy->gpiod_en, phy->en_polarity);
usleep_range(10000, 15000); usleep_range(10000, 15000);
gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
usleep_range(10000, 15000); usleep_range(10000, 15000);
phy->powered = 0; phy->powered = 0;
...@@ -874,106 +869,20 @@ static void pn544_hci_i2c_fw_work(struct work_struct *work) ...@@ -874,106 +869,20 @@ static void pn544_hci_i2c_fw_work(struct work_struct *work)
} }
} }
static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client) static const struct acpi_gpio_params enable_gpios = { 1, 0, false };
{ static const struct acpi_gpio_params firmware_gpios = { 2, 0, false };
struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
struct gpio_desc *gpiod_en, *gpiod_fw;
struct device *dev = &client->dev;
/* Get EN GPIO from ACPI */
gpiod_en = devm_gpiod_get_index(dev, PN544_GPIO_NAME_EN, 1,
GPIOD_OUT_LOW);
if (IS_ERR(gpiod_en)) {
nfc_err(dev, "Unable to get EN GPIO\n");
return -ENODEV;
}
phy->gpio_en = desc_to_gpio(gpiod_en);
/* Get FW GPIO from ACPI */
gpiod_fw = devm_gpiod_get_index(dev, PN544_GPIO_NAME_FW, 2,
GPIOD_OUT_LOW);
if (IS_ERR(gpiod_fw)) {
nfc_err(dev, "Unable to get FW GPIO\n");
return -ENODEV;
}
phy->gpio_fw = desc_to_gpio(gpiod_fw);
return 0;
}
static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
{
struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
struct device_node *pp;
int ret;
pp = client->dev.of_node;
if (!pp) {
ret = -ENODEV;
goto err_dt;
}
/* Obtention of EN GPIO from device tree */
ret = of_get_named_gpio(pp, "enable-gpios", 0);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
nfc_err(&client->dev,
"Failed to get EN gpio, error: %d\n", ret);
goto err_dt;
}
phy->gpio_en = ret;
/* Configuration of EN GPIO */
ret = gpio_request(phy->gpio_en, PN544_GPIO_NAME_EN);
if (ret) {
nfc_err(&client->dev, "Fail EN pin\n");
goto err_dt;
}
ret = gpio_direction_output(phy->gpio_en, 0);
if (ret) {
nfc_err(&client->dev, "Fail EN pin direction\n");
goto err_gpio_en;
}
/* Obtention of FW GPIO from device tree */
ret = of_get_named_gpio(pp, "firmware-gpios", 0);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
nfc_err(&client->dev,
"Failed to get FW gpio, error: %d\n", ret);
goto err_gpio_en;
}
phy->gpio_fw = ret;
/* Configuration of FW GPIO */
ret = gpio_request(phy->gpio_fw, PN544_GPIO_NAME_FW);
if (ret) {
nfc_err(&client->dev, "Fail FW pin\n");
goto err_gpio_en;
}
ret = gpio_direction_output(phy->gpio_fw, 0);
if (ret) {
nfc_err(&client->dev, "Fail FW pin direction\n");
goto err_gpio_fw;
}
return 0;
err_gpio_fw: static const struct acpi_gpio_mapping acpi_pn544_gpios[] = {
gpio_free(phy->gpio_fw); { "enable-gpios", &enable_gpios, 1 },
err_gpio_en: { "firmware-gpios", &firmware_gpios, 1 },
gpio_free(phy->gpio_en); { },
err_dt: };
return ret;
}
static int pn544_hci_i2c_probe(struct i2c_client *client, static int pn544_hci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev;
struct pn544_i2c_phy *phy; struct pn544_i2c_phy *phy;
struct pn544_nfc_platform_data *pdata;
int r = 0; int r = 0;
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
...@@ -995,53 +904,33 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, ...@@ -995,53 +904,33 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
phy->i2c_dev = client; phy->i2c_dev = client;
i2c_set_clientdata(client, phy); i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data; r = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_pn544_gpios);
if (r)
/* No platform data, using device tree. */ dev_dbg(dev, "Unable to add GPIO mapping table\n");
if (!pdata && client->dev.of_node) {
r = pn544_hci_i2c_of_request_resources(client);
if (r) {
nfc_err(&client->dev, "No DT data\n");
return r;
}
/* Using platform data. */
} else if (pdata) {
if (pdata->request_resources == NULL) {
nfc_err(&client->dev, "request_resources() missing\n");
return -EINVAL;
}
r = pdata->request_resources(client); /* Get EN GPIO */
if (r) { phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
nfc_err(&client->dev, if (IS_ERR(phy->gpiod_en)) {
"Cannot get platform resources\n"); nfc_err(dev, "Unable to get EN GPIO\n");
return r; return PTR_ERR(phy->gpiod_en);
} }
phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); /* Get FW GPIO */
phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); phy->gpiod_fw = devm_gpiod_get(dev, "firmware", GPIOD_OUT_LOW);
/* Using ACPI */ if (IS_ERR(phy->gpiod_fw)) {
} else if (ACPI_HANDLE(&client->dev)) { nfc_err(dev, "Unable to get FW GPIO\n");
r = pn544_hci_i2c_acpi_request_resources(client); return PTR_ERR(phy->gpiod_fw);
if (r) {
nfc_err(&client->dev,
"Cannot get ACPI data\n");
return r;
}
} else {
nfc_err(&client->dev, "No platform data\n");
return -EINVAL;
} }
pn544_hci_i2c_platform_init(phy); pn544_hci_i2c_platform_init(phy);
r = request_threaded_irq(client->irq, NULL, pn544_hci_i2c_irq_thread_fn, r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, pn544_hci_i2c_irq_thread_fn,
PN544_HCI_I2C_DRIVER_NAME, phy); IRQF_TRIGGER_RISING | IRQF_ONESHOT,
PN544_HCI_I2C_DRIVER_NAME, phy);
if (r < 0) { if (r < 0) {
nfc_err(&client->dev, "Unable to register IRQ handler\n"); nfc_err(&client->dev, "Unable to register IRQ handler\n");
goto err_rti; return r;
} }
r = pn544_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, r = pn544_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
...@@ -1049,28 +938,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, ...@@ -1049,28 +938,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
PN544_HCI_I2C_LLC_MAX_PAYLOAD, PN544_HCI_I2C_LLC_MAX_PAYLOAD,
pn544_hci_i2c_fw_download, &phy->hdev); pn544_hci_i2c_fw_download, &phy->hdev);
if (r < 0) if (r < 0)
goto err_hci; return r;
return 0; return 0;
err_hci:
free_irq(client->irq, phy);
err_rti:
if (!pdata) {
gpio_free(phy->gpio_en);
gpio_free(phy->gpio_fw);
} else if (pdata->free_resources) {
pdata->free_resources();
}
return r;
} }
static int pn544_hci_i2c_remove(struct i2c_client *client) static int pn544_hci_i2c_remove(struct i2c_client *client)
{ {
struct pn544_i2c_phy *phy = i2c_get_clientdata(client); struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
...@@ -1083,17 +958,7 @@ static int pn544_hci_i2c_remove(struct i2c_client *client) ...@@ -1083,17 +958,7 @@ static int pn544_hci_i2c_remove(struct i2c_client *client)
if (phy->powered) if (phy->powered)
pn544_hci_i2c_disable(phy); pn544_hci_i2c_disable(phy);
free_irq(client->irq, phy); acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev));
/* No platform data, GPIOs have been requested by this driver */
if (!pdata) {
gpio_free(phy->gpio_en);
gpio_free(phy->gpio_fw);
/* Using platform data */
} else if (pdata->free_resources) {
pdata->free_resources();
}
return 0; return 0;
} }
......
...@@ -21,8 +21,9 @@ ...@@ -21,8 +21,9 @@
#define VERSION "0.1" #define VERSION "0.1"
#define SONY_VENDOR_ID 0x054c #define SONY_VENDOR_ID 0x054c
#define RCS380_PRODUCT_ID 0x06c1 #define RCS380S_PRODUCT_ID 0x06c1
#define RCS380P_PRODUCT_ID 0x06c3
#define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ #define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
NFC_PROTO_MIFARE_MASK | \ NFC_PROTO_MIFARE_MASK | \
...@@ -725,23 +726,33 @@ static int port100_submit_urb_for_ack(struct port100 *dev, gfp_t flags) ...@@ -725,23 +726,33 @@ static int port100_submit_urb_for_ack(struct port100 *dev, gfp_t flags)
static int port100_send_ack(struct port100 *dev) static int port100_send_ack(struct port100 *dev)
{ {
int rc; int rc = 0;
mutex_lock(&dev->out_urb_lock); mutex_lock(&dev->out_urb_lock);
init_completion(&dev->cmd_cancel_done); /*
* If prior cancel is in-flight (dev->cmd_cancel == true), we
* can skip to send cancel. Then this will wait the prior
* cancel, or merged into the next cancel rarely if next
* cancel was started before waiting done. In any case, this
* will be waked up soon or later.
*/
if (!dev->cmd_cancel) {
reinit_completion(&dev->cmd_cancel_done);
usb_kill_urb(dev->out_urb); usb_kill_urb(dev->out_urb);
dev->out_urb->transfer_buffer = ack_frame; dev->out_urb->transfer_buffer = ack_frame;
dev->out_urb->transfer_buffer_length = sizeof(ack_frame); dev->out_urb->transfer_buffer_length = sizeof(ack_frame);
rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
/* Set the cmd_cancel flag only if the URB has been successfully /*
* submitted. It will be reset by the out URB completion callback * Set the cmd_cancel flag only if the URB has been
* port100_send_complete(). * successfully submitted. It will be reset by the out
*/ * URB completion callback port100_send_complete().
dev->cmd_cancel = !rc; */
dev->cmd_cancel = !rc;
}
mutex_unlock(&dev->out_urb_lock); mutex_unlock(&dev->out_urb_lock);
...@@ -928,8 +939,8 @@ static void port100_send_complete(struct urb *urb) ...@@ -928,8 +939,8 @@ static void port100_send_complete(struct urb *urb)
struct port100 *dev = urb->context; struct port100 *dev = urb->context;
if (dev->cmd_cancel) { if (dev->cmd_cancel) {
complete_all(&dev->cmd_cancel_done);
dev->cmd_cancel = false; dev->cmd_cancel = false;
complete(&dev->cmd_cancel_done);
} }
switch (urb->status) { switch (urb->status) {
...@@ -1477,7 +1488,8 @@ static struct nfc_digital_ops port100_digital_ops = { ...@@ -1477,7 +1488,8 @@ static struct nfc_digital_ops port100_digital_ops = {
}; };
static const struct usb_device_id port100_table[] = { static const struct usb_device_id port100_table[] = {
{ USB_DEVICE(SONY_VENDOR_ID, RCS380_PRODUCT_ID), }, { USB_DEVICE(SONY_VENDOR_ID, RCS380S_PRODUCT_ID), },
{ USB_DEVICE(SONY_VENDOR_ID, RCS380P_PRODUCT_ID), },
{ } { }
}; };
MODULE_DEVICE_TABLE(usb, port100_table); MODULE_DEVICE_TABLE(usb, port100_table);
...@@ -1538,11 +1550,13 @@ static int port100_probe(struct usb_interface *interface, ...@@ -1538,11 +1550,13 @@ static int port100_probe(struct usb_interface *interface,
usb_fill_bulk_urb(dev->out_urb, dev->udev, usb_fill_bulk_urb(dev->out_urb, dev->udev,
usb_sndbulkpipe(dev->udev, out_endpoint), usb_sndbulkpipe(dev->udev, out_endpoint),
NULL, 0, port100_send_complete, dev); NULL, 0, port100_send_complete, dev);
dev->out_urb->transfer_flags = URB_ZERO_PACKET;
dev->skb_headroom = PORT100_FRAME_HEADER_LEN + dev->skb_headroom = PORT100_FRAME_HEADER_LEN +
PORT100_COMM_RF_HEAD_MAX_LEN; PORT100_COMM_RF_HEAD_MAX_LEN;
dev->skb_tailroom = PORT100_FRAME_TAIL_LEN; dev->skb_tailroom = PORT100_FRAME_TAIL_LEN;
init_completion(&dev->cmd_cancel_done);
INIT_WORK(&dev->cmd_complete_work, port100_wq_cmd_complete); INIT_WORK(&dev->cmd_complete_work, port100_wq_cmd_complete);
/* The first thing to do with the Port-100 is to set the command type /* The first thing to do with the Port-100 is to set the command type
......
...@@ -959,10 +959,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, ...@@ -959,10 +959,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
unsigned long quirks = 0; unsigned long quirks = 0;
info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL); info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL);
if (!info) { if (!info)
r = -ENOMEM; return -ENOMEM;
goto err_alloc_hdev;
}
info->phy_ops = phy_ops; info->phy_ops = phy_ops;
info->phy_id = phy_id; info->phy_id = phy_id;
...@@ -978,8 +976,10 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, ...@@ -978,8 +976,10 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
* persistent info to discriminate 2 identical chips * persistent info to discriminate 2 identical chips
*/ */
dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES); dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES);
if (dev_num >= ST21NFCA_NUM_DEVICES) if (dev_num >= ST21NFCA_NUM_DEVICES) {
return -ENODEV; r = -ENODEV;
goto err_alloc_hdev;
}
set_bit(dev_num, dev_mask); set_bit(dev_num, dev_mask);
......
...@@ -20,17 +20,15 @@ ...@@ -20,17 +20,15 @@
#include <linux/crc-ccitt.h> #include <linux/crc-ccitt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/platform_data/st21nfca.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/nfc/hci.h> #include <net/nfc/hci.h>
...@@ -60,6 +58,7 @@ ...@@ -60,6 +58,7 @@
#define IS_START_OF_FRAME(buf) (buf[0] == ST21NFCA_SOF_EOF && \ #define IS_START_OF_FRAME(buf) (buf[0] == ST21NFCA_SOF_EOF && \
buf[1] == 0) buf[1] == 0)
#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c" #define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"
#define ST21NFCA_GPIO_NAME_EN "enable" #define ST21NFCA_GPIO_NAME_EN "enable"
...@@ -68,9 +67,7 @@ struct st21nfca_i2c_phy { ...@@ -68,9 +67,7 @@ struct st21nfca_i2c_phy {
struct i2c_client *i2c_dev; struct i2c_client *i2c_dev;
struct nfc_hci_dev *hdev; struct nfc_hci_dev *hdev;
unsigned int gpio_ena; struct gpio_desc *gpiod_ena;
unsigned int irq_polarity;
struct st21nfca_se_status se_status; struct st21nfca_se_status se_status;
struct sk_buff *pending_skb; struct sk_buff *pending_skb;
...@@ -151,7 +148,7 @@ static int st21nfca_hci_i2c_enable(void *phy_id) ...@@ -151,7 +148,7 @@ static int st21nfca_hci_i2c_enable(void *phy_id)
{ {
struct st21nfca_i2c_phy *phy = phy_id; struct st21nfca_i2c_phy *phy = phy_id;
gpio_set_value(phy->gpio_ena, 1); gpiod_set_value(phy->gpiod_ena, 1);
phy->powered = 1; phy->powered = 1;
phy->run_mode = ST21NFCA_HCI_MODE; phy->run_mode = ST21NFCA_HCI_MODE;
...@@ -164,7 +161,7 @@ static void st21nfca_hci_i2c_disable(void *phy_id) ...@@ -164,7 +161,7 @@ static void st21nfca_hci_i2c_disable(void *phy_id)
{ {
struct st21nfca_i2c_phy *phy = phy_id; struct st21nfca_i2c_phy *phy = phy_id;
gpio_set_value(phy->gpio_ena, 0); gpiod_set_value(phy->gpiod_ena, 0);
phy->powered = 0; phy->powered = 0;
} }
...@@ -507,33 +504,14 @@ static struct nfc_phy_ops i2c_phy_ops = { ...@@ -507,33 +504,14 @@ static struct nfc_phy_ops i2c_phy_ops = {
static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client) static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client)
{ {
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
struct gpio_desc *gpiod_ena;
struct device *dev = &client->dev; struct device *dev = &client->dev;
u8 tmp;
/* Get EN GPIO from ACPI */ /* Get EN GPIO from ACPI */
gpiod_ena = devm_gpiod_get_index(dev, ST21NFCA_GPIO_NAME_EN, 1, phy->gpiod_ena = devm_gpiod_get_index(dev, ST21NFCA_GPIO_NAME_EN, 1,
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (!IS_ERR(gpiod_ena)) { if (IS_ERR(phy->gpiod_ena)) {
nfc_err(dev, "Unable to get ENABLE GPIO\n"); nfc_err(dev, "Unable to get ENABLE GPIO\n");
return -ENODEV; return PTR_ERR(phy->gpiod_ena);
}
phy->gpio_ena = desc_to_gpio(gpiod_ena);
phy->irq_polarity = irq_get_trigger_type(client->irq);
phy->se_status.is_ese_present = false;
phy->se_status.is_uicc_present = false;
if (device_property_present(dev, "ese-present")) {
device_property_read_u8(dev, "ese-present", &tmp);
phy->se_status.is_ese_present = tmp;
}
if (device_property_present(dev, "uicc-present")) {
device_property_read_u8(dev, "uicc-present", &tmp);
phy->se_status.is_uicc_present = tmp;
} }
return 0; return 0;
...@@ -542,70 +520,16 @@ static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client) ...@@ -542,70 +520,16 @@ static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client)
static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
{ {
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
struct device_node *pp; struct device *dev = &client->dev;
int gpio;
int r;
pp = client->dev.of_node;
if (!pp)
return -ENODEV;
/* Get GPIO from device tree */ /* Get GPIO from device tree */
gpio = of_get_named_gpio(pp, "enable-gpios", 0); phy->gpiod_ena = devm_gpiod_get_index(dev, ST21NFCA_GPIO_NAME_EN, 0,
if (gpio < 0) { GPIOD_OUT_HIGH);
nfc_err(&client->dev, "Failed to retrieve enable-gpios from device tree\n"); if (IS_ERR(phy->gpiod_ena)) {
return gpio; nfc_err(dev, "Failed to request enable pin\n");
} return PTR_ERR(phy->gpiod_ena);
/* GPIO request and configuration */
r = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH,
ST21NFCA_GPIO_NAME_EN);
if (r) {
nfc_err(&client->dev, "Failed to request enable pin\n");
return r;
} }
phy->gpio_ena = gpio;
phy->irq_polarity = irq_get_trigger_type(client->irq);
phy->se_status.is_ese_present =
of_property_read_bool(pp, "ese-present");
phy->se_status.is_uicc_present =
of_property_read_bool(pp, "uicc-present");
return 0;
}
static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
{
struct st21nfca_nfc_platform_data *pdata;
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
int r;
pdata = client->dev.platform_data;
if (pdata == NULL) {
nfc_err(&client->dev, "No platform data\n");
return -EINVAL;
}
/* store for later use */
phy->gpio_ena = pdata->gpio_ena;
phy->irq_polarity = pdata->irq_polarity;
if (phy->gpio_ena > 0) {
r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
GPIOF_OUT_INIT_HIGH,
ST21NFCA_GPIO_NAME_EN);
if (r) {
pr_err("%s : ena gpio_request failed\n", __FILE__);
return r;
}
}
phy->se_status.is_ese_present = pdata->is_ese_present;
phy->se_status.is_uicc_present = pdata->is_uicc_present;
return 0; return 0;
} }
...@@ -613,7 +537,6 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, ...@@ -613,7 +537,6 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct st21nfca_i2c_phy *phy; struct st21nfca_i2c_phy *phy;
struct st21nfca_nfc_platform_data *pdata;
int r; int r;
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
...@@ -639,19 +562,12 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, ...@@ -639,19 +562,12 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
mutex_init(&phy->phy_lock); mutex_init(&phy->phy_lock);
i2c_set_clientdata(client, phy); i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data; if (client->dev.of_node) {
if (!pdata && client->dev.of_node) {
r = st21nfca_hci_i2c_of_request_resources(client); r = st21nfca_hci_i2c_of_request_resources(client);
if (r) { if (r) {
nfc_err(&client->dev, "No platform data\n"); nfc_err(&client->dev, "No platform data\n");
return r; return r;
} }
} else if (pdata) {
r = st21nfca_hci_i2c_request_resources(client);
if (r) {
nfc_err(&client->dev, "Cannot get platform resources\n");
return r;
}
} else if (ACPI_HANDLE(&client->dev)) { } else if (ACPI_HANDLE(&client->dev)) {
r = st21nfca_hci_i2c_acpi_request_resources(client); r = st21nfca_hci_i2c_acpi_request_resources(client);
if (r) { if (r) {
...@@ -663,6 +579,11 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, ...@@ -663,6 +579,11 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
phy->se_status.is_ese_present =
device_property_read_bool(&client->dev, "ese-present");
phy->se_status.is_uicc_present =
device_property_read_bool(&client->dev, "uicc-present");
r = st21nfca_hci_platform_init(phy); r = st21nfca_hci_platform_init(phy);
if (r < 0) { if (r < 0) {
nfc_err(&client->dev, "Unable to reboot st21nfca\n"); nfc_err(&client->dev, "Unable to reboot st21nfca\n");
...@@ -671,7 +592,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, ...@@ -671,7 +592,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
r = devm_request_threaded_irq(&client->dev, client->irq, NULL, r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
st21nfca_hci_irq_thread_fn, st21nfca_hci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT, IRQF_ONESHOT,
ST21NFCA_HCI_DRIVER_NAME, phy); ST21NFCA_HCI_DRIVER_NAME, phy);
if (r < 0) { if (r < 0) {
nfc_err(&client->dev, "Unable to register IRQ handler\n"); nfc_err(&client->dev, "Unable to register IRQ handler\n");
......
...@@ -124,6 +124,9 @@ ...@@ -124,6 +124,9 @@
NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK) NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK)
#define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */ #define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */
#define TRF7970A_13MHZ_CLOCK_FREQUENCY 13560000
#define TRF7970A_27MHZ_CLOCK_FREQUENCY 27120000
#define TRF7970A_RX_SKB_ALLOC_SIZE 256 #define TRF7970A_RX_SKB_ALLOC_SIZE 256
...@@ -441,6 +444,7 @@ struct trf7970a { ...@@ -441,6 +444,7 @@ struct trf7970a {
u8 iso_ctrl_tech; u8 iso_ctrl_tech;
u8 modulator_sys_clk_ctrl; u8 modulator_sys_clk_ctrl;
u8 special_fcn_reg1; u8 special_fcn_reg1;
u8 io_ctrl;
unsigned int guard_time; unsigned int guard_time;
int technology; int technology;
int framing; int framing;
...@@ -1048,6 +1052,11 @@ static int trf7970a_init(struct trf7970a *trf) ...@@ -1048,6 +1052,11 @@ static int trf7970a_init(struct trf7970a *trf)
if (ret) if (ret)
goto err_out; goto err_out;
ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL,
trf->io_ctrl | TRF7970A_REG_IO_CTRL_VRS(0x1));
if (ret)
goto err_out;
ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0);
if (ret) if (ret)
goto err_out; goto err_out;
...@@ -1056,12 +1065,11 @@ static int trf7970a_init(struct trf7970a *trf) ...@@ -1056,12 +1065,11 @@ static int trf7970a_init(struct trf7970a *trf)
trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON;
ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 0); ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL,
trf->modulator_sys_clk_ctrl);
if (ret) if (ret)
goto err_out; goto err_out;
trf->modulator_sys_clk_ctrl = 0;
ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS, ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS,
TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 | TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 |
TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32); TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32);
...@@ -1181,27 +1189,37 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech) ...@@ -1181,27 +1189,37 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech)
switch (tech) { switch (tech) {
case NFC_DIGITAL_RF_TECH_106A: case NFC_DIGITAL_RF_TECH_106A:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443A_106; trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443A_106;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_OOK;
trf->guard_time = TRF7970A_GUARD_TIME_NFCA; trf->guard_time = TRF7970A_GUARD_TIME_NFCA;
break; break;
case NFC_DIGITAL_RF_TECH_106B: case NFC_DIGITAL_RF_TECH_106B:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443B_106; trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443B_106;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_ASK10;
trf->guard_time = TRF7970A_GUARD_TIME_NFCB; trf->guard_time = TRF7970A_GUARD_TIME_NFCB;
break; break;
case NFC_DIGITAL_RF_TECH_212F: case NFC_DIGITAL_RF_TECH_212F:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_212; trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_212;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_ASK10;
trf->guard_time = TRF7970A_GUARD_TIME_NFCF; trf->guard_time = TRF7970A_GUARD_TIME_NFCF;
break; break;
case NFC_DIGITAL_RF_TECH_424F: case NFC_DIGITAL_RF_TECH_424F:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_424; trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_424;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_ASK10;
trf->guard_time = TRF7970A_GUARD_TIME_NFCF; trf->guard_time = TRF7970A_GUARD_TIME_NFCF;
break; break;
case NFC_DIGITAL_RF_TECH_ISO15693: case NFC_DIGITAL_RF_TECH_ISO15693:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_OOK;
trf->guard_time = TRF7970A_GUARD_TIME_15693; trf->guard_time = TRF7970A_GUARD_TIME_15693;
break; break;
default: default:
...@@ -1571,17 +1589,23 @@ static int trf7970a_tg_config_rf_tech(struct trf7970a *trf, int tech) ...@@ -1571,17 +1589,23 @@ static int trf7970a_tg_config_rf_tech(struct trf7970a *trf, int tech)
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
TRF7970A_ISO_CTRL_NFC_CE | TRF7970A_ISO_CTRL_NFC_CE |
TRF7970A_ISO_CTRL_NFC_CE_14443A; TRF7970A_ISO_CTRL_NFC_CE_14443A;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_OOK;
break; break;
case NFC_DIGITAL_RF_TECH_212F: case NFC_DIGITAL_RF_TECH_212F:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
TRF7970A_ISO_CTRL_NFC_NFCF_212; TRF7970A_ISO_CTRL_NFC_NFCF_212;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_ASK10;
break; break;
case NFC_DIGITAL_RF_TECH_424F: case NFC_DIGITAL_RF_TECH_424F:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
TRF7970A_ISO_CTRL_NFC_NFCF_424; TRF7970A_ISO_CTRL_NFC_NFCF_424;
trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; trf->modulator_sys_clk_ctrl =
(trf->modulator_sys_clk_ctrl & 0xf8) |
TRF7970A_MODULATOR_DEPTH_ASK10;
break; break;
default: default:
dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);
...@@ -1749,7 +1773,7 @@ static int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, ...@@ -1749,7 +1773,7 @@ static int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
goto out_err; goto out_err;
ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL, ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL,
TRF7970A_REG_IO_CTRL_VRS(0x1)); trf->io_ctrl | TRF7970A_REG_IO_CTRL_VRS(0x1));
if (ret) if (ret)
goto out_err; goto out_err;
...@@ -1885,8 +1909,10 @@ static int trf7970a_power_up(struct trf7970a *trf) ...@@ -1885,8 +1909,10 @@ static int trf7970a_power_up(struct trf7970a *trf)
usleep_range(5000, 6000); usleep_range(5000, 6000);
if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) { if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) {
gpio_set_value(trf->en2_gpio, 1); if (gpio_is_valid(trf->en2_gpio)) {
usleep_range(1000, 2000); gpio_set_value(trf->en2_gpio, 1);
usleep_range(1000, 2000);
}
} }
gpio_set_value(trf->en_gpio, 1); gpio_set_value(trf->en_gpio, 1);
...@@ -1914,7 +1940,8 @@ static int trf7970a_power_down(struct trf7970a *trf) ...@@ -1914,7 +1940,8 @@ static int trf7970a_power_down(struct trf7970a *trf)
} }
gpio_set_value(trf->en_gpio, 0); gpio_set_value(trf->en_gpio, 0);
gpio_set_value(trf->en2_gpio, 0); if (gpio_is_valid(trf->en2_gpio))
gpio_set_value(trf->en2_gpio, 0);
ret = regulator_disable(trf->regulator); ret = regulator_disable(trf->regulator);
if (ret) if (ret)
...@@ -1987,6 +2014,7 @@ static int trf7970a_probe(struct spi_device *spi) ...@@ -1987,6 +2014,7 @@ static int trf7970a_probe(struct spi_device *spi)
struct device_node *np = spi->dev.of_node; struct device_node *np = spi->dev.of_node;
struct trf7970a *trf; struct trf7970a *trf;
int uvolts, autosuspend_delay, ret; int uvolts, autosuspend_delay, ret;
u32 clk_freq = TRF7970A_13MHZ_CLOCK_FREQUENCY;
if (!np) { if (!np) {
dev_err(&spi->dev, "No Device Tree entry\n"); dev_err(&spi->dev, "No Device Tree entry\n");
...@@ -2032,15 +2060,23 @@ static int trf7970a_probe(struct spi_device *spi) ...@@ -2032,15 +2060,23 @@ static int trf7970a_probe(struct spi_device *spi)
trf->en2_gpio = of_get_named_gpio(np, "ti,enable-gpios", 1); trf->en2_gpio = of_get_named_gpio(np, "ti,enable-gpios", 1);
if (!gpio_is_valid(trf->en2_gpio)) { if (!gpio_is_valid(trf->en2_gpio)) {
dev_err(trf->dev, "No EN2 GPIO property\n"); dev_info(trf->dev, "No EN2 GPIO property\n");
return trf->en2_gpio; } else {
ret = devm_gpio_request_one(trf->dev, trf->en2_gpio,
GPIOF_DIR_OUT | GPIOF_INIT_LOW, "trf7970a EN2");
if (ret) {
dev_err(trf->dev, "Can't request EN2 GPIO: %d\n", ret);
return ret;
}
} }
ret = devm_gpio_request_one(trf->dev, trf->en2_gpio, of_property_read_u32(np, "clock-frequency", &clk_freq);
GPIOF_DIR_OUT | GPIOF_INIT_LOW, "trf7970a EN2"); if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) ||
if (ret) { (clk_freq != TRF7970A_13MHZ_CLOCK_FREQUENCY)) {
dev_err(trf->dev, "Can't request EN2 GPIO: %d\n", ret); dev_err(trf->dev,
return ret; "clock-frequency (%u Hz) unsupported\n",
clk_freq);
return -EINVAL;
} }
if (of_property_read_bool(np, "en2-rf-quirk")) if (of_property_read_bool(np, "en2-rf-quirk"))
...@@ -2077,6 +2113,24 @@ static int trf7970a_probe(struct spi_device *spi) ...@@ -2077,6 +2113,24 @@ static int trf7970a_probe(struct spi_device *spi)
if (uvolts > 4000000) if (uvolts > 4000000)
trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
if (IS_ERR(trf->regulator)) {
ret = PTR_ERR(trf->regulator);
dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
goto err_destroy_lock;
}
ret = regulator_enable(trf->regulator);
if (ret) {
dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
goto err_destroy_lock;
}
if (regulator_get_voltage(trf->regulator) == 1800000) {
trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
}
trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops,
TRF7970A_SUPPORTED_PROTOCOLS, TRF7970A_SUPPORTED_PROTOCOLS,
NFC_DIGITAL_DRV_CAPS_IN_CRC | NFC_DIGITAL_DRV_CAPS_IN_CRC |
......
/*
* Driver include for the PN544 NFC chip.
*
* Copyright (C) Nokia Corporation
*
* Author: Jari Vanhala <ext-jari.vanhala@nokia.com>
* Contact: Matti Aaltoenn <matti.j.aaltonen@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms 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 _PN544_H_
#define _PN544_H_
#include <linux/i2c.h>
enum {
NFC_GPIO_ENABLE,
NFC_GPIO_FW_RESET,
NFC_GPIO_IRQ
};
/* board config */
struct pn544_nfc_platform_data {
int (*request_resources) (struct i2c_client *client);
void (*free_resources) (void);
void (*enable) (int fw);
int (*test) (void);
void (*disable) (void);
int (*get_gpio)(int type);
};
#endif /* _PN544_H_ */
/*
* Driver include for the ST21NFCA NFC chip.
*
* Copyright (C) 2014 STMicroelectronics SAS. 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 _ST21NFCA_HCI_H_
#define _ST21NFCA_HCI_H_
#include <linux/i2c.h>
#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
struct st21nfca_nfc_platform_data {
unsigned int gpio_ena;
unsigned int irq_polarity;
bool is_ese_present;
bool is_uicc_present;
};
#endif /* _ST21NFCA_HCI_H_ */
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#define nfc_dbg(dev, fmt, ...) dev_dbg((dev), "NFC: " fmt, ##__VA_ARGS__)
#define nfc_info(dev, fmt, ...) dev_info((dev), "NFC: " fmt, ##__VA_ARGS__) #define nfc_info(dev, fmt, ...) dev_info((dev), "NFC: " fmt, ##__VA_ARGS__)
#define nfc_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__) #define nfc_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__)
......
...@@ -304,6 +304,17 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev) ...@@ -304,6 +304,17 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev)
return -EMSGSIZE; return -EMSGSIZE;
} }
static int nfc_genl_setup_device_added(struct nfc_dev *dev, struct sk_buff *msg)
{
if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) ||
nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) ||
nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) ||
nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode))
return -1;
return 0;
}
int nfc_genl_device_added(struct nfc_dev *dev) int nfc_genl_device_added(struct nfc_dev *dev)
{ {
struct sk_buff *msg; struct sk_buff *msg;
...@@ -318,10 +329,7 @@ int nfc_genl_device_added(struct nfc_dev *dev) ...@@ -318,10 +329,7 @@ int nfc_genl_device_added(struct nfc_dev *dev)
if (!hdr) if (!hdr)
goto free_msg; goto free_msg;
if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || if (nfc_genl_setup_device_added(dev, msg))
nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) ||
nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up))
goto nla_put_failure; goto nla_put_failure;
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
...@@ -597,11 +605,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, ...@@ -597,11 +605,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
if (cb) if (cb)
genl_dump_check_consistent(cb, hdr, &nfc_genl_family); genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || if (nfc_genl_setup_device_added(dev, msg))
nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) ||
nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) ||
nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode))
goto nla_put_failure; goto nla_put_failure;
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
...@@ -919,7 +923,7 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info) ...@@ -919,7 +923,7 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
rc = nfc_activate_target(dev, target_idx, protocol); rc = nfc_activate_target(dev, target_idx, protocol);
nfc_put_device(dev); nfc_put_device(dev);
return 0; return rc;
} }
static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment