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:
- spi-max-frequency: Maximum SPI frequency (<= 2000000).
- interrupt-parent: phandle of parent interrupt handler.
- interrupts: A single interrupt specifier.
- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the
TRF7970A.
- ti,enable-gpios: One or two GPIO entries used for 'EN' and 'EN2' pins on the
TRF7970A. EN2 is optional.
- vin-supply: Regulator for supply voltage to VIN pin
Optional SoC Specific Properties:
......@@ -21,6 +21,8 @@ Optional SoC Specific Properties:
- 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.
- 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):
......@@ -39,10 +41,12 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1):
<&gpio2 5 GPIO_ACTIVE_LOW>;
vin-supply = <&ldo3_reg>;
vin-voltage-override = <5000000>;
vdd-io-supply = <&ldo2_reg>;
autosuspend-delay = <30000>;
irq-status-read-quirk;
en2-rf-quirk;
t5t-rmb-extra-byte-quirk;
clock-frequency = <27120000>;
status = "okay";
};
};
......@@ -8876,8 +8876,6 @@ S: Supported
F: drivers/net/ethernet/qlogic/netxen/
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>
L: linux-wireless@vger.kernel.org
L: linux-nfc@lists.01.org (subscribers-only)
......
......@@ -5,17 +5,6 @@
menu "Near Field Communication (NFC) devices"
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
tristate "Texas Instruments TRF7970a NFC driver"
depends on SPI && NFC_DIGITAL
......
......@@ -6,7 +6,6 @@ obj-$(CONFIG_NFC_FDP) += fdp/
obj-$(CONFIG_NFC_PN544) += pn544/
obj-$(CONFIG_NFC_MICROREAD) += microread/
obj-$(CONFIG_NFC_PN533) += pn533/
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o
obj-$(CONFIG_NFC_SIM) += nfcsim.o
obj-$(CONFIG_NFC_PORT100) += port100.o
......
......@@ -210,14 +210,14 @@ static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
struct sk_buff *skb;
int r;
client = phy->i2c_dev;
dev_dbg(&client->dev, "%s\n", __func__);
if (!phy || irq != phy->i2c_dev->irq) {
WARN_ON_ONCE(1);
return IRQ_NONE;
}
client = phy->i2c_dev;
dev_dbg(&client->dev, "%s\n", __func__);
r = fdp_nci_i2c_read(phy, &skb);
if (r == -EREMOTEIO)
......
......@@ -17,7 +17,7 @@
*/
#include <linux/module.h>
#include <linux/unaligned/access_ok.h>
#include <asm/unaligned.h>
#include <linux/firmware.h>
#include <linux/nfc.h>
#include <net/nfc/nci.h>
......@@ -281,12 +281,11 @@ static int process_state_fw_dnld(struct nfcmrvl_private *priv,
return -EINVAL;
}
skb_pull(skb, 1);
memcpy(&len, skb->data, 2);
len = get_unaligned_le16(skb->data);
skb_pull(skb, 2);
comp_len = get_unaligned_le16(skb->data);
memcpy(&comp_len, skb->data, 2);
skb_pull(skb, 2);
len = get_unaligned_le16(&len);
comp_len = get_unaligned_le16(&comp_len);
if (((~len) & 0xFFFF) != comp_len) {
nfc_err(priv->dev, "bad len complement: %x %x %x",
len, comp_len, (~len & 0xFFFF));
......
......@@ -26,7 +26,6 @@
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include "nfcmrvl.h"
#define SPI_WAIT_HANDSHAKE 1
......@@ -96,10 +95,9 @@ static int nfcmrvl_spi_nci_send(struct nfcmrvl_private *priv,
/* Send the SPI packet */
err = nci_spi_send(drv_data->nci_spi, &drv_data->handshake_completion,
skb);
if (err != 0) {
if (err)
nfc_err(priv->dev, "spi_send failed %d", err);
kfree_skb(skb);
}
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 @@
#include <linux/completion.h>
#include <linux/firmware.h>
#include <linux/nfc.h>
#include <linux/unaligned/access_ok.h>
#include <asm/unaligned.h>
#include "nxp-nci.h"
......
......@@ -29,14 +29,13 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/nfc.h>
#include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/platform_data/nxp-nci.h>
#include <linux/unaligned/access_ok.h>
#include <asm/unaligned.h>
#include <net/nfc/nfc.h>
......@@ -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);
if (r < 0) {
/* Retry, chip was in standby */
usleep_range(110000, 120000);
msleep(110);
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,
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;
*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)
{
struct pn533_i2c_phy *phy = dev->phy;
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 */
int rc;
......@@ -206,14 +206,6 @@ static int pn533_i2c_probe(struct i2c_client *client,
phy->i2c_dev = client;
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,
PN533_NO_TYPE_B_PROTOCOLS,
PN533_PROTO_REQ_ACK_RESP,
......@@ -223,16 +215,32 @@ static int pn533_i2c_probe(struct i2c_client *client,
if (IS_ERR(priv)) {
r = PTR_ERR(priv);
goto err_register;
return r;
}
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;
err_register:
fn_setup_err:
free_irq(client->irq, phy);
irq_rqst_err:
pn533_unregister_device(phy->priv);
return r;
}
......@@ -242,10 +250,10 @@ static int pn533_i2c_remove(struct i2c_client *client)
dev_dbg(&client->dev, "%s\n", __func__);
pn533_unregister_device(phy->priv);
free_irq(client->irq, phy);
pn533_unregister_device(phy->priv);
return 0;
}
......
......@@ -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)
{
struct pn533_cmd *cmd = dev->cmd;
int status = cmd->status;
struct sk_buff *resp;
int status, rc = 0;
struct sk_buff *req = cmd->req;
struct sk_buff *resp = cmd->resp;
if (!cmd) {
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) {
rc = cmd->complete_cb(dev, cmd->complete_cb_context,
......@@ -399,8 +403,14 @@ static int pn533_send_async_complete(struct pn533 *dev)
goto done;
}
/* when no response is set we got interrupted */
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);
......@@ -434,12 +444,14 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
mutex_lock(&dev->cmd_lock);
if (!dev->cmd_pending) {
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req);
if (rc)
if (rc) {
dev->cmd = NULL;
goto error;
}
dev->cmd_pending = 1;
dev->cmd = cmd;
goto unlock;
}
......@@ -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);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req);
if (rc < 0)
if (rc < 0) {
dev->cmd = NULL;
kfree(cmd);
else
dev->cmd = cmd;
}
return rc;
}
......@@ -550,14 +563,15 @@ static void pn533_wq_cmd(struct work_struct *work)
mutex_unlock(&dev->cmd_lock);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, cmd->req);
if (rc < 0) {
dev->cmd = NULL;
dev_kfree_skb(cmd->req);
kfree(cmd);
return;
}
dev->cmd = cmd;
}
struct pn533_sync_cmd_response {
......@@ -2556,6 +2570,31 @@ static int pn533_setup(struct pn533 *dev)
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,
u32 protocols,
enum pn533_protocol_type protocol_type,
......@@ -2565,7 +2604,6 @@ struct pn533 *pn533_register_device(u32 device_type,
struct device *dev,
struct device *parent)
{
struct pn533_fw_version fw_ver;
struct pn533 *priv;
int rc = -ENOMEM;
......@@ -2608,15 +2646,6 @@ struct pn533 *pn533_register_device(u32 device_type,
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->ops->tx_header_len +
PN533_CMD_DATAEXCH_HEAD_LEN,
......@@ -2633,15 +2662,8 @@ struct pn533 *pn533_register_device(u32 device_type,
if (rc)
goto free_nfc_dev;
rc = pn533_setup(priv);
if (rc)
goto unregister_nfc_dev;
return priv;
unregister_nfc_dev:
nfc_unregister_device(priv->nfc_dev);
free_nfc_dev:
nfc_free_device(priv->nfc_dev);
......
......@@ -231,6 +231,7 @@ struct pn533 *pn533_register_device(u32 device_type,
struct device *dev,
struct device *parent);
int pn533_finalize_setup(struct pn533 *dev);
void pn533_unregister_device(struct pn533 *priv);
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)
static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
{
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 */
int rc;
phy->out_urb->transfer_buffer = ack;
phy->out_urb->transfer_buffer = (u8 *)ack;
phy->out_urb->transfer_buffer_length = sizeof(ack);
rc = usb_submit_urb(phy->out_urb, flags);
......@@ -543,6 +543,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
phy->priv = priv;
rc = pn533_finalize_setup(priv);
if (rc)
goto error;
usb_set_intfdata(interface, phy);
return 0;
......
......@@ -21,17 +21,13 @@
#include <linux/crc-ccitt.h>
#include <linux/module.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/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_data/pn544.h>
#include <asm/unaligned.h>
#include <net/nfc/hci.h>
......@@ -165,8 +161,9 @@ struct pn544_i2c_phy {
struct i2c_client *i2c_dev;
struct nfc_hci_dev *hdev;
unsigned int gpio_en;
unsigned int gpio_fw;
struct gpio_desc *gpiod_en;
struct gpio_desc *gpiod_fw;
unsigned int en_polarity;
u8 hw_variant;
......@@ -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");
/* 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++) {
phy->en_polarity = polarity;
retry = 3;
while (retry--) {
/* power off */
gpio_set_value_cansleep(phy->gpio_en,
!phy->en_polarity);
gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
usleep_range(10000, 15000);
/* 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);
/* send reset */
......@@ -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");
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)
{
gpio_set_value_cansleep(phy->gpio_fw,
run_mode == PN544_FW_MODE ? 1 : 0);
gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity);
gpiod_set_value_cansleep(phy->gpiod_fw, run_mode == PN544_FW_MODE ? 1 : 0);
gpiod_set_value_cansleep(phy->gpiod_en, phy->en_polarity);
usleep_range(10000, 15000);
phy->run_mode = run_mode;
......@@ -269,14 +264,14 @@ static void pn544_hci_i2c_disable(void *phy_id)
{
struct pn544_i2c_phy *phy = phy_id;
gpio_set_value_cansleep(phy->gpio_fw, 0);
gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity);
gpiod_set_value_cansleep(phy->gpiod_fw, 0);
gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
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);
gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity);
gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
usleep_range(10000, 15000);
phy->powered = 0;
......@@ -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)
{
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);
static const struct acpi_gpio_params enable_gpios = { 1, 0, false };
static const struct acpi_gpio_params firmware_gpios = { 2, 0, false };
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:
gpio_free(phy->gpio_fw);
err_gpio_en:
gpio_free(phy->gpio_en);
err_dt:
return ret;
}
static const struct acpi_gpio_mapping acpi_pn544_gpios[] = {
{ "enable-gpios", &enable_gpios, 1 },
{ "firmware-gpios", &firmware_gpios, 1 },
{ },
};
static int pn544_hci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct pn544_i2c_phy *phy;
struct pn544_nfc_platform_data *pdata;
int r = 0;
dev_dbg(&client->dev, "%s\n", __func__);
......@@ -995,53 +904,33 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
phy->i2c_dev = client;
i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data;
r = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_pn544_gpios);
if (r)
dev_dbg(dev, "Unable to add GPIO mapping table\n");
/* No platform data, using device tree. */
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);
if (r) {
nfc_err(&client->dev,
"Cannot get platform resources\n");
return r;
/* Get EN GPIO */
phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(phy->gpiod_en)) {
nfc_err(dev, "Unable to get EN GPIO\n");
return PTR_ERR(phy->gpiod_en);
}
phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
/* Using ACPI */
} else if (ACPI_HANDLE(&client->dev)) {
r = pn544_hci_i2c_acpi_request_resources(client);
if (r) {
nfc_err(&client->dev,
"Cannot get ACPI data\n");
return r;
}
} else {
nfc_err(&client->dev, "No platform data\n");
return -EINVAL;
/* Get FW GPIO */
phy->gpiod_fw = devm_gpiod_get(dev, "firmware", GPIOD_OUT_LOW);
if (IS_ERR(phy->gpiod_fw)) {
nfc_err(dev, "Unable to get FW GPIO\n");
return PTR_ERR(phy->gpiod_fw);
}
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,
pn544_hci_i2c_irq_thread_fn,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
PN544_HCI_I2C_DRIVER_NAME, phy);
if (r < 0) {
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,
......@@ -1049,28 +938,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
PN544_HCI_I2C_LLC_MAX_PAYLOAD,
pn544_hci_i2c_fw_download, &phy->hdev);
if (r < 0)
goto err_hci;
return r;
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)
{
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__);
......@@ -1083,17 +958,7 @@ static int pn544_hci_i2c_remove(struct i2c_client *client)
if (phy->powered)
pn544_hci_i2c_disable(phy);
free_irq(client->irq, phy);
/* 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();
}
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev));
return 0;
}
......
......@@ -22,7 +22,8 @@
#define VERSION "0.1"
#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 | \
NFC_PROTO_MIFARE_MASK | \
......@@ -725,11 +726,19 @@ static int port100_submit_urb_for_ack(struct port100 *dev, gfp_t flags)
static int port100_send_ack(struct port100 *dev)
{
int rc;
int rc = 0;
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);
......@@ -737,11 +746,13 @@ static int port100_send_ack(struct port100 *dev)
dev->out_urb->transfer_buffer_length = sizeof(ack_frame);
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
* port100_send_complete().
/*
* Set the cmd_cancel flag only if the URB has been
* successfully submitted. It will be reset by the out
* URB completion callback port100_send_complete().
*/
dev->cmd_cancel = !rc;
}
mutex_unlock(&dev->out_urb_lock);
......@@ -928,8 +939,8 @@ static void port100_send_complete(struct urb *urb)
struct port100 *dev = urb->context;
if (dev->cmd_cancel) {
complete_all(&dev->cmd_cancel_done);
dev->cmd_cancel = false;
complete(&dev->cmd_cancel_done);
}
switch (urb->status) {
......@@ -1477,7 +1488,8 @@ static struct nfc_digital_ops port100_digital_ops = {
};
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);
......@@ -1538,11 +1550,13 @@ static int port100_probe(struct usb_interface *interface,
usb_fill_bulk_urb(dev->out_urb, dev->udev,
usb_sndbulkpipe(dev->udev, out_endpoint),
NULL, 0, port100_send_complete, dev);
dev->out_urb->transfer_flags = URB_ZERO_PACKET;
dev->skb_headroom = PORT100_FRAME_HEADER_LEN +
PORT100_COMM_RF_HEAD_MAX_LEN;
dev->skb_tailroom = PORT100_FRAME_TAIL_LEN;
init_completion(&dev->cmd_cancel_done);
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
......
......@@ -959,10 +959,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
unsigned long quirks = 0;
info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL);
if (!info) {
r = -ENOMEM;
goto err_alloc_hdev;
}
if (!info)
return -ENOMEM;
info->phy_ops = phy_ops;
info->phy_id = phy_id;
......@@ -978,8 +976,10 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
* persistent info to discriminate 2 identical chips
*/
dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES);
if (dev_num >= ST21NFCA_NUM_DEVICES)
return -ENODEV;
if (dev_num >= ST21NFCA_NUM_DEVICES) {
r = -ENODEV;
goto err_alloc_hdev;
}
set_bit(dev_num, dev_mask);
......
......@@ -20,17 +20,15 @@
#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>
#include <linux/platform_data/st21nfca.h>
#include <asm/unaligned.h>
#include <net/nfc/hci.h>
......@@ -60,6 +58,7 @@
#define IS_START_OF_FRAME(buf) (buf[0] == ST21NFCA_SOF_EOF && \
buf[1] == 0)
#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"
#define ST21NFCA_GPIO_NAME_EN "enable"
......@@ -68,9 +67,7 @@ struct st21nfca_i2c_phy {
struct i2c_client *i2c_dev;
struct nfc_hci_dev *hdev;
unsigned int gpio_ena;
unsigned int irq_polarity;
struct gpio_desc *gpiod_ena;
struct st21nfca_se_status se_status;
struct sk_buff *pending_skb;
......@@ -151,7 +148,7 @@ static int st21nfca_hci_i2c_enable(void *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->run_mode = ST21NFCA_HCI_MODE;
......@@ -164,7 +161,7 @@ static void st21nfca_hci_i2c_disable(void *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;
}
......@@ -507,33 +504,14 @@ static struct nfc_phy_ops i2c_phy_ops = {
static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client)
{
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
struct gpio_desc *gpiod_ena;
struct device *dev = &client->dev;
u8 tmp;
/* 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);
if (!IS_ERR(gpiod_ena)) {
if (IS_ERR(phy->gpiod_ena)) {
nfc_err(dev, "Unable to get ENABLE GPIO\n");
return -ENODEV;
}
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 PTR_ERR(phy->gpiod_ena);
}
return 0;
......@@ -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)
{
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
struct device_node *pp;
int gpio;
int r;
pp = client->dev.of_node;
if (!pp)
return -ENODEV;
struct device *dev = &client->dev;
/* Get GPIO from device tree */
gpio = of_get_named_gpio(pp, "enable-gpios", 0);
if (gpio < 0) {
nfc_err(&client->dev, "Failed to retrieve enable-gpios from device tree\n");
return gpio;
}
/* 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->gpiod_ena = devm_gpiod_get_index(dev, ST21NFCA_GPIO_NAME_EN, 0,
GPIOD_OUT_HIGH);
if (IS_ERR(phy->gpiod_ena)) {
nfc_err(dev, "Failed to request enable pin\n");
return PTR_ERR(phy->gpiod_ena);
}
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;
}
......@@ -613,7 +537,6 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct st21nfca_i2c_phy *phy;
struct st21nfca_nfc_platform_data *pdata;
int r;
dev_dbg(&client->dev, "%s\n", __func__);
......@@ -639,19 +562,12 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
mutex_init(&phy->phy_lock);
i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data;
if (!pdata && client->dev.of_node) {
if (client->dev.of_node) {
r = st21nfca_hci_i2c_of_request_resources(client);
if (r) {
nfc_err(&client->dev, "No platform data\n");
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)) {
r = st21nfca_hci_i2c_acpi_request_resources(client);
if (r) {
......@@ -663,6 +579,11 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
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);
if (r < 0) {
nfc_err(&client->dev, "Unable to reboot st21nfca\n");
......@@ -671,7 +592,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
st21nfca_hci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT,
IRQF_ONESHOT,
ST21NFCA_HCI_DRIVER_NAME, phy);
if (r < 0) {
nfc_err(&client->dev, "Unable to register IRQ handler\n");
......
......@@ -124,6 +124,9 @@
NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK)
#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
......@@ -441,6 +444,7 @@ struct trf7970a {
u8 iso_ctrl_tech;
u8 modulator_sys_clk_ctrl;
u8 special_fcn_reg1;
u8 io_ctrl;
unsigned int guard_time;
int technology;
int framing;
......@@ -1048,6 +1052,11 @@ static int trf7970a_init(struct trf7970a *trf)
if (ret)
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);
if (ret)
goto err_out;
......@@ -1056,12 +1065,11 @@ static int trf7970a_init(struct trf7970a *trf)
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)
goto err_out;
trf->modulator_sys_clk_ctrl = 0;
ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS,
TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 |
TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32);
......@@ -1181,27 +1189,37 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech)
switch (tech) {
case NFC_DIGITAL_RF_TECH_106A:
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;
break;
case NFC_DIGITAL_RF_TECH_106B:
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;
break;
case NFC_DIGITAL_RF_TECH_212F:
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;
break;
case NFC_DIGITAL_RF_TECH_424F:
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;
break;
case NFC_DIGITAL_RF_TECH_ISO15693:
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;
break;
default:
......@@ -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 |
TRF7970A_ISO_CTRL_NFC_CE |
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;
case NFC_DIGITAL_RF_TECH_212F:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
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;
case NFC_DIGITAL_RF_TECH_424F:
trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
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;
default:
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,
goto out_err;
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)
goto out_err;
......@@ -1885,9 +1909,11 @@ static int trf7970a_power_up(struct trf7970a *trf)
usleep_range(5000, 6000);
if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) {
if (gpio_is_valid(trf->en2_gpio)) {
gpio_set_value(trf->en2_gpio, 1);
usleep_range(1000, 2000);
}
}
gpio_set_value(trf->en_gpio, 1);
......@@ -1914,6 +1940,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
}
gpio_set_value(trf->en_gpio, 0);
if (gpio_is_valid(trf->en2_gpio))
gpio_set_value(trf->en2_gpio, 0);
ret = regulator_disable(trf->regulator);
......@@ -1987,6 +2014,7 @@ static int trf7970a_probe(struct spi_device *spi)
struct device_node *np = spi->dev.of_node;
struct trf7970a *trf;
int uvolts, autosuspend_delay, ret;
u32 clk_freq = TRF7970A_13MHZ_CLOCK_FREQUENCY;
if (!np) {
dev_err(&spi->dev, "No Device Tree entry\n");
......@@ -2032,16 +2060,24 @@ static int trf7970a_probe(struct spi_device *spi)
trf->en2_gpio = of_get_named_gpio(np, "ti,enable-gpios", 1);
if (!gpio_is_valid(trf->en2_gpio)) {
dev_err(trf->dev, "No EN2 GPIO property\n");
return trf->en2_gpio;
}
dev_info(trf->dev, "No EN2 GPIO property\n");
} 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;
}
}
of_property_read_u32(np, "clock-frequency", &clk_freq);
if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) ||
(clk_freq != TRF7970A_13MHZ_CLOCK_FREQUENCY)) {
dev_err(trf->dev,
"clock-frequency (%u Hz) unsupported\n",
clk_freq);
return -EINVAL;
}
if (of_property_read_bool(np, "en2-rf-quirk"))
trf->quirks |= TRF7970A_QUIRK_EN2_MUST_STAY_LOW;
......@@ -2077,6 +2113,24 @@ static int trf7970a_probe(struct spi_device *spi)
if (uvolts > 4000000)
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,
TRF7970A_SUPPORTED_PROTOCOLS,
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 @@
#include <linux/device.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_err(dev, fmt, ...) dev_err((dev), "NFC: " fmt, ##__VA_ARGS__)
......
......@@ -304,6 +304,17 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev)
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)
{
struct sk_buff *msg;
......@@ -318,10 +329,7 @@ int nfc_genl_device_added(struct nfc_dev *dev)
if (!hdr)
goto free_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))
if (nfc_genl_setup_device_added(dev, msg))
goto nla_put_failure;
genlmsg_end(msg, hdr);
......@@ -597,11 +605,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
if (cb)
genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
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))
if (nfc_genl_setup_device_added(dev, msg))
goto nla_put_failure;
genlmsg_end(msg, hdr);
......@@ -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);
nfc_put_device(dev);
return 0;
return rc;
}
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