summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-09-26 13:37:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-09-26 13:37:02 -0400
commit330bd4ec9d046a6e6f8b7cf4a53c2d15b7705e00 (patch)
treed278d8325e1e1cfca1ecfaf592158dcec10539f2
parent687b93082c0469fe9fe85583e6265a3d910cd89a (diff)
parent094e93592433312548dd5e43d7b24b152f658063 (diff)
downloadop-kernel-dev-330bd4ec9d046a6e6f8b7cf4a53c2d15b7705e00.zip
op-kernel-dev-330bd4ec9d046a6e6f8b7cf4a53c2d15b7705e00.tar.gz
Merge tag 'nfc-next-3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next
Samuel Ortiz <sameo@linux.intel.com> says: "NFC: 3.18 pull request This is the NFC pull request for 3.18. We've had major updates for TI and ST Microelectronics drivers: For TI's trf7970a driver: - Target mode support for trf7970a - Suspend/resume support for trf7970a - DT properties additions to handle different quirks - A bunch of fixes for smartphone IOP related issues For ST Microelectronics' ST21NFCA and ST21NFCB drivers: - ISO15693 support for st21nfcb - checkpatch and sparse related warning fixes - Code cleanups and a few minor fixes Finally, Marvell add ISO15693 support to the NCI stack, together with a couple of NCI fixes." Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--Documentation/devicetree/bindings/net/nfc/st21nfcb.txt2
-rw-r--r--Documentation/devicetree/bindings/net/nfc/trf7970a.txt8
-rw-r--r--drivers/nfc/st21nfca/i2c.c34
-rw-r--r--drivers/nfc/st21nfca/st21nfca.c59
-rw-r--r--drivers/nfc/st21nfca/st21nfca.h21
-rw-r--r--drivers/nfc/st21nfca/st21nfca_dep.c59
-rw-r--r--drivers/nfc/st21nfcb/i2c.c67
-rw-r--r--drivers/nfc/st21nfcb/ndlc.c6
-rw-r--r--drivers/nfc/st21nfcb/ndlc.h4
-rw-r--r--drivers/nfc/st21nfcb/st21nfcb.c27
-rw-r--r--drivers/nfc/st21nfcb/st21nfcb.h2
-rw-r--r--drivers/nfc/trf7970a.c1059
-rw-r--r--include/net/nfc/nci.h16
-rw-r--r--include/net/nfc/nci_core.h9
-rw-r--r--net/nfc/digital_dep.c101
-rw-r--r--net/nfc/nci/core.c21
-rw-r--r--net/nfc/nci/data.c7
-rw-r--r--net/nfc/nci/ntf.c40
18 files changed, 1188 insertions, 354 deletions
diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
index 3b58ae4..9005608 100644
--- a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
@@ -26,7 +26,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
clock-frequency = <400000>;
interrupt-parent = <&gpio5>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
};
diff --git a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
index 1e43613..7c89ca2 100644
--- a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
+++ b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
@@ -13,6 +13,11 @@ Optional SoC Specific Properties:
- pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller.
- autosuspend-delay: Specify autosuspend delay in milliseconds.
+- vin-voltage-override: Specify voltage of VIN pin in microvolts.
+- irq-status-read-quirk: Specify that the trf7970a being used has the
+ "IRQ Status Read" erratum.
+- en2-rf-quirk: Specify that the trf7970a being used has the "EN2 RF"
+ erratum.
Example (for ARM-based BeagleBone with TRF7970A on SPI1):
@@ -30,7 +35,10 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1):
ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>,
<&gpio2 5 GPIO_ACTIVE_LOW>;
vin-supply = <&ldo3_reg>;
+ vin-voltage-override = <5000000>;
autosuspend-delay = <30000>;
+ irq-status-read-quirk;
+ en2-rf-quirk;
status = "okay";
};
};
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index ff31939..0ea756b 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -271,6 +271,7 @@ static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb)
static int get_frame_size(u8 *buf, int buflen)
{
int len = 0;
+
if (buf[len + 1] == ST21NFCA_SOF_EOF)
return 0;
@@ -311,6 +312,7 @@ static int check_crc(u8 *buf, int buflen)
static int st21nfca_hci_i2c_repack(struct sk_buff *skb)
{
int i, j, r, size;
+
if (skb->len < 1 || (skb->len > 1 && skb->data[1] != 0))
return -EBADMSG;
@@ -525,24 +527,19 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
}
/* GPIO request and configuration */
- r = devm_gpio_request(&client->dev, gpio, "clf_enable");
+ r = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH,
+ "clf_enable");
if (r) {
nfc_err(&client->dev, "Failed to request enable pin\n");
return -ENODEV;
}
- r = gpio_direction_output(gpio, 1);
- if (r) {
- nfc_err(&client->dev, "Failed to set enable pin direction as output\n");
- return -ENODEV;
- }
phy->gpio_ena = gpio;
/* IRQ */
r = irq_of_parse_and_map(pp, 0);
if (r < 0) {
- nfc_err(&client->dev,
- "Unable to get irq, error: %d\n", r);
+ nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
return r;
}
@@ -576,32 +573,20 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
phy->gpio_ena = pdata->gpio_ena;
phy->irq_polarity = pdata->irq_polarity;
- r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up");
+ r = devm_gpio_request_one(&client->dev, phy->gpio_irq, GPIOF_IN,
+ "wake_up");
if (r) {
pr_err("%s : gpio_request failed\n", __FILE__);
return -ENODEV;
}
- r = gpio_direction_input(phy->gpio_irq);
- if (r) {
- pr_err("%s : gpio_direction_input failed\n", __FILE__);
- return -ENODEV;
- }
-
if (phy->gpio_ena > 0) {
- r = devm_gpio_request(&client->dev,
- phy->gpio_ena, "clf_enable");
+ r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
+ GPIOF_OUT_INIT_HIGH, "clf_enable");
if (r) {
pr_err("%s : ena gpio_request failed\n", __FILE__);
return -ENODEV;
}
- r = gpio_direction_output(phy->gpio_ena, 1);
-
- if (r) {
- pr_err("%s : ena gpio_direction_output failed\n",
- __FILE__);
- return -ENODEV;
- }
}
/* IRQ */
@@ -711,7 +696,6 @@ static struct i2c_driver st21nfca_hci_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = ST21NFCA_HCI_I2C_DRIVER_NAME,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(of_st21nfca_i2c_match),
},
.probe = st21nfca_hci_i2c_probe,
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index a902b05..a89e56c 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -34,7 +34,7 @@
#define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x30
#define ST21NFCA_RF_READER_ISO15693_GATE 0x12
-#define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01
+#define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01
/*
* Reader gate for communication with contact-less cards using Type A
@@ -45,21 +45,42 @@
#define ST21NFCA_RF_READER_14443_3_A_ATQA 0x03
#define ST21NFCA_RF_READER_14443_3_A_SAK 0x04
+#define ST21NFCA_RF_READER_F_DATARATE 0x01
+#define ST21NFCA_RF_READER_F_DATARATE_106 0x01
+#define ST21NFCA_RF_READER_F_DATARATE_212 0x02
+#define ST21NFCA_RF_READER_F_DATARATE_424 0x04
+#define ST21NFCA_RF_READER_F_POL_REQ 0x02
+#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000
+#define ST21NFCA_RF_READER_F_NFCID2 0x03
+#define ST21NFCA_RF_READER_F_NFCID1 0x04
+
+#define ST21NFCA_RF_CARD_F_MODE 0x01
+#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04
+#define ST21NFCA_RF_CARD_F_NFCID1 0x05
+#define ST21NFCA_RF_CARD_F_SENS_RES 0x06
+#define ST21NFCA_RF_CARD_F_SEL_RES 0x07
+#define ST21NFCA_RF_CARD_F_DATARATE 0x08
+#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01
+
#define ST21NFCA_DEVICE_MGNT_GATE 0x01
#define ST21NFCA_DEVICE_MGNT_PIPE 0x02
-#define ST21NFCA_DM_GETINFO 0x13
-#define ST21NFCA_DM_GETINFO_PIPE_LIST 0x02
-#define ST21NFCA_DM_GETINFO_PIPE_INFO 0x01
-#define ST21NFCA_DM_PIPE_CREATED 0x02
-#define ST21NFCA_DM_PIPE_OPEN 0x04
-#define ST21NFCA_DM_RF_ACTIVE 0x80
-#define ST21NFCA_DM_DISCONNECT 0x30
+#define ST21NFCA_DM_GETINFO 0x13
+#define ST21NFCA_DM_GETINFO_PIPE_LIST 0x02
+#define ST21NFCA_DM_GETINFO_PIPE_INFO 0x01
+#define ST21NFCA_DM_PIPE_CREATED 0x02
+#define ST21NFCA_DM_PIPE_OPEN 0x04
+#define ST21NFCA_DM_RF_ACTIVE 0x80
+#define ST21NFCA_DM_DISCONNECT 0x30
#define ST21NFCA_DM_IS_PIPE_OPEN(p) \
((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
-#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/
+#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/
+#define ST21NFCA_EVT_FIELD_ON 0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
+#define ST21NFCA_EVT_FIELD_OFF 0x14
static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
@@ -355,8 +376,8 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
if (r < 0)
return r;
- pol_req =
- be32_to_cpu(ST21NFCA_RF_READER_F_POL_REQ_DEFAULT);
+ pol_req = be32_to_cpu((__force __be32)
+ ST21NFCA_RF_READER_F_POL_REQ_DEFAULT);
r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
ST21NFCA_RF_READER_F_POL_REQ,
(u8 *) &pol_req, 4);
@@ -790,6 +811,7 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
struct nfc_target *target)
{
u8 fwi = 0x11;
+
switch (target->hci_reader_gate) {
case NFC_HCI_RF_READER_A_GATE:
case NFC_HCI_RF_READER_B_GATE:
@@ -839,20 +861,16 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
if (gate == ST21NFCA_RF_CARD_F_GATE) {
r = st21nfca_tm_event_send_data(hdev, skb, gate);
if (r < 0)
- goto exit;
+ return r;
return 0;
- } else {
- info->dep_info.curr_nfc_dep_pni = 0;
- return 1;
}
- break;
+ info->dep_info.curr_nfc_dep_pni = 0;
+ return 1;
default:
return 1;
}
kfree_skb(skb);
return 0;
-exit:
- return r;
}
static struct nfc_hci_ops st21nfca_hci_ops = {
@@ -904,8 +922,11 @@ 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)
- goto err_alloc_hdev;
+ return -ENODEV;
+
+ set_bit(dev_num, dev_mask);
scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x",
"ST21AH", dev_num);
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 96fe5a6..a0b77f1 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -82,30 +82,9 @@ struct st21nfca_hci_info {
#define ST21NFCA_WR_XCHG_DATA 0x10
#define ST21NFCA_RF_READER_F_GATE 0x14
-#define ST21NFCA_RF_READER_F_DATARATE 0x01
-#define ST21NFCA_RF_READER_F_DATARATE_106 0x01
-#define ST21NFCA_RF_READER_F_DATARATE_212 0x02
-#define ST21NFCA_RF_READER_F_DATARATE_424 0x04
-#define ST21NFCA_RF_READER_F_POL_REQ 0x02
-#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000
-#define ST21NFCA_RF_READER_F_NFCID2 0x03
-#define ST21NFCA_RF_READER_F_NFCID1 0x04
-#define ST21NFCA_RF_READER_F_SENS_RES 0x05
#define ST21NFCA_RF_CARD_F_GATE 0x24
-#define ST21NFCA_RF_CARD_F_MODE 0x01
-#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04
-#define ST21NFCA_RF_CARD_F_NFCID1 0x05
-#define ST21NFCA_RF_CARD_F_SENS_RES 0x06
-#define ST21NFCA_RF_CARD_F_SEL_RES 0x07
-#define ST21NFCA_RF_CARD_F_DATARATE 0x08
-#define ST21NFCA_RF_CARD_F_DATARATE_106 0x00
-#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01
#define ST21NFCA_EVT_SEND_DATA 0x10
-#define ST21NFCA_EVT_FIELD_ON 0x11
-#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
-#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
-#define ST21NFCA_EVT_FIELD_OFF 0x14
#endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c
index b2d9957..bfb6df5 100644
--- a/drivers/nfc/st21nfca/st21nfca_dep.c
+++ b/drivers/nfc/st21nfca/st21nfca_dep.c
@@ -121,6 +121,7 @@ static void st21nfca_tx_work(struct work_struct *work)
struct nfc_dev *dev;
struct sk_buff *skb;
+
if (info) {
dev = info->hdev->ndev;
skb = info->dep_info.tx_pending;
@@ -128,9 +129,8 @@ static void st21nfca_tx_work(struct work_struct *work)
device_lock(&dev->dev);
nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
- ST21NFCA_WR_XCHG_DATA,
- skb->data, skb->len,
- info->async_cb, info);
+ ST21NFCA_WR_XCHG_DATA, skb->data, skb->len,
+ info->async_cb, info);
device_unlock(&dev->dev);
kfree_skb(skb);
}
@@ -185,8 +185,10 @@ static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev,
info->dep_info.curr_nfc_dep_pni = 0;
- return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+ r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+ kfree_skb(skb);
+ return r;
}
static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
@@ -197,10 +199,6 @@ static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
int r;
skb_trim(skb, skb->len - 1);
- if (IS_ERR(skb)) {
- r = PTR_ERR(skb);
- goto exit;
- }
if (!skb->len) {
r = -EIO;
@@ -214,6 +212,11 @@ static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
atr_req = (struct st21nfca_atr_req *)skb->data;
+ if (atr_req->length < sizeof(struct st21nfca_atr_req)) {
+ r = -EPROTO;
+ goto exit;
+ }
+
r = st21nfca_tm_send_atr_res(hdev, atr_req);
if (r)
goto exit;
@@ -237,7 +240,6 @@ static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
struct st21nfca_psl_res *psl_res;
struct sk_buff *skb;
u8 bitrate[2] = {0, 0};
-
int r;
skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL);
@@ -254,6 +256,8 @@ static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+ if (r < 0)
+ goto error;
/*
* ST21NFCA only support P2P passive.
@@ -269,8 +273,11 @@ static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
}
/* Send an event to change bitrate change event to card f */
- return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+ r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2);
+error:
+ kfree_skb(skb);
+ return r;
}
static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
@@ -280,11 +287,6 @@ static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
int r;
skb_trim(skb, skb->len - 1);
- if (IS_ERR(skb)) {
- r = PTR_ERR(skb);
- skb = NULL;
- goto exit;
- }
if (!skb->len) {
r = -EIO;
@@ -314,7 +316,7 @@ int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb)
*skb_push(skb, 1) = skb->len;
r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
- ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+ ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
kfree_skb(skb);
return r;
@@ -330,11 +332,6 @@ static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
skb_trim(skb, skb->len - 1);
- if (IS_ERR(skb)) {
- r = PTR_ERR(skb);
- skb = NULL;
- goto exit;
- }
size = 4;
@@ -368,12 +365,6 @@ static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
break;
}
- if (IS_ERR(skb)) {
- r = PTR_ERR(skb);
- skb = NULL;
- goto exit;
- }
-
skb_pull(skb, size);
return nfc_tm_data_received(hdev->ndev, skb);
@@ -437,8 +428,6 @@ static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
*skb_push(skb, 1) = info->dep_info.to | 0x10;
st21nfca_im_send_pdu(info, skb);
-
- kfree_skb(skb);
}
#define ST21NFCA_CB_TYPE_READER_F 1
@@ -452,7 +441,7 @@ static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
if (err != 0)
return;
- if (IS_ERR(skb))
+ if (!skb)
return;
switch (info->async_cb_type) {
@@ -484,8 +473,7 @@ static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
ST21NFCA_PP2LRI(atr_res->ppi));
break;
default:
- if (err == 0)
- kfree_skb(skb);
+ kfree_skb(skb);
break;
}
}
@@ -522,7 +510,7 @@ int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len)
memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE);
target = hdev->ndev->targets;
- if (target->sensf_res)
+ if (target->sensf_res_len > 0)
memcpy(atr_req->nfcid3, target->sensf_res,
target->sensf_res_len);
else
@@ -565,7 +553,7 @@ static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
if (err != 0)
return;
- if (IS_ERR(skb))
+ if (!skb)
return;
switch (info->async_cb_type) {
@@ -615,8 +603,7 @@ static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
}
exit:
- if (err == 0)
- kfree_skb(skb);
+ kfree_skb(skb);
}
int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb)
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c
index 8af880e..c5d2427 100644
--- a/drivers/nfc/st21nfcb/i2c.c
+++ b/drivers/nfc/st21nfcb/i2c.c
@@ -17,24 +17,16 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
-#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
-#include <linux/firmware.h>
-#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/st21nfcb.h>
-#include <net/nfc/nci.h>
-#include <net/nfc/llc.h>
-#include <net/nfc/nfc.h>
-
#include "ndlc.h"
#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
@@ -63,12 +55,6 @@ struct st21nfcb_i2c_phy {
unsigned int irq_polarity;
int powered;
-
- /*
- * < 0 if hardware error occured (e.g. i2c err)
- * and prevents normal operation.
- */
- int hard_fault;
};
#define I2C_DUMP_SKB(info, skb) \
@@ -122,8 +108,8 @@ static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb);
- if (phy->hard_fault != 0)
- return phy->hard_fault;
+ if (phy->ndlc->hard_fault != 0)
+ return phy->ndlc->hard_fault;
r = i2c_master_send(client, skb->data, skb->len);
if (r == -EREMOTEIO) { /* Retry, chip was in standby */
@@ -168,11 +154,11 @@ static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
if (r == -EREMOTEIO) { /* Retry, chip was in standby */
usleep_range(1000, 4000);
r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
- } else if (r != ST21NFCB_NCI_I2C_MIN_SIZE) {
- nfc_err(&client->dev, "cannot read ndlc & nci header\n");
- return -EREMOTEIO;
}
+ if (r != ST21NFCB_NCI_I2C_MIN_SIZE)
+ return -EREMOTEIO;
+
len = be16_to_cpu(*(__be16 *) (buf + 2));
if (len > ST21NFCB_NCI_I2C_MAX_SIZE) {
nfc_err(&client->dev, "invalid frame len\n");
@@ -224,7 +210,7 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
client = phy->i2c_dev;
dev_dbg(&client->dev, "IRQ\n");
- if (phy->hard_fault)
+ if (phy->ndlc->hard_fault)
return IRQ_HANDLED;
if (!phy->powered) {
@@ -233,13 +219,8 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
}
r = st21nfcb_nci_i2c_read(phy, &skb);
- if (r == -EREMOTEIO) {
- phy->hard_fault = r;
- ndlc_recv(phy->ndlc, NULL);
- return IRQ_HANDLED;
- } else if (r == -ENOMEM || r == -EBADMSG) {
+ if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG)
return IRQ_HANDLED;
- }
ndlc_recv(phy->ndlc, skb);
@@ -273,25 +254,18 @@ static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
}
/* GPIO request and configuration */
- r = devm_gpio_request(&client->dev, gpio, "clf_reset");
+ r = devm_gpio_request_one(&client->dev, gpio,
+ GPIOF_OUT_INIT_HIGH, "clf_reset");
if (r) {
nfc_err(&client->dev, "Failed to request reset pin\n");
return -ENODEV;
}
-
- r = gpio_direction_output(gpio, 1);
- if (r) {
- nfc_err(&client->dev,
- "Failed to set reset pin direction as output\n");
- return -ENODEV;
- }
phy->gpio_reset = gpio;
/* IRQ */
r = irq_of_parse_and_map(pp, 0);
if (r < 0) {
- nfc_err(&client->dev,
- "Unable to get irq, error: %d\n", r);
+ nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
return r;
}
@@ -325,32 +299,20 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
phy->gpio_reset = pdata->gpio_reset;
phy->irq_polarity = pdata->irq_polarity;
- r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up");
+ r = devm_gpio_request_one(&client->dev, phy->gpio_irq,
+ GPIOF_IN, "clf_irq");
if (r) {
pr_err("%s : gpio_request failed\n", __FILE__);
return -ENODEV;
}
- r = gpio_direction_input(phy->gpio_irq);
- if (r) {
- pr_err("%s : gpio_direction_input failed\n", __FILE__);
- return -ENODEV;
- }
-
- r = devm_gpio_request(&client->dev,
- phy->gpio_reset, "clf_reset");
+ r = devm_gpio_request_one(&client->dev,
+ phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset");
if (r) {
pr_err("%s : reset gpio_request failed\n", __FILE__);
return -ENODEV;
}
- r = gpio_direction_output(phy->gpio_reset, 1);
- if (r) {
- pr_err("%s : reset gpio_direction_output failed\n",
- __FILE__);
- return -ENODEV;
- }
-
/* IRQ */
irq = gpio_to_irq(phy->gpio_irq);
if (irq < 0) {
@@ -448,7 +410,6 @@ static struct i2c_driver st21nfcb_nci_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = ST21NFCB_NCI_I2C_DRIVER_NAME,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(of_st21nfcb_i2c_match),
},
.probe = st21nfcb_nci_i2c_probe,
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c
index 83c97c3..e7bff89 100644
--- a/drivers/nfc/st21nfcb/ndlc.c
+++ b/drivers/nfc/st21nfcb/ndlc.c
@@ -112,6 +112,10 @@ static void llt_ndlc_send_queue(struct llt_ndlc *ndlc)
ndlc->t1_active = true;
mod_timer(&ndlc->t1_timer, time_sent +
msecs_to_jiffies(NDLC_TIMER_T1));
+ /* start timer t2 for chip availability */
+ ndlc->t2_active = true;
+ mod_timer(&ndlc->t2_timer, time_sent +
+ msecs_to_jiffies(NDLC_TIMER_T2));
}
}
@@ -207,7 +211,7 @@ static void llt_ndlc_sm_work(struct work_struct *work)
ndlc->t2_active = false;
ndlc->t1_active = false;
del_timer_sync(&ndlc->t1_timer);
-
+ del_timer_sync(&ndlc->t2_timer);
ndlc_close(ndlc);
ndlc->hard_fault = -EREMOTEIO;
}
diff --git a/drivers/nfc/st21nfcb/ndlc.h b/drivers/nfc/st21nfcb/ndlc.h
index c30a2f0..b28140e 100644
--- a/drivers/nfc/st21nfcb/ndlc.h
+++ b/drivers/nfc/st21nfcb/ndlc.h
@@ -42,6 +42,10 @@ struct llt_ndlc {
struct device *dev;
+ /*
+ * < 0 if hardware error occured
+ * and prevents normal operation.
+ */
int hard_fault;
};
diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c
index 4d95863..ea63d58 100644
--- a/drivers/nfc/st21nfcb/st21nfcb.c
+++ b/drivers/nfc/st21nfcb/st21nfcb.c
@@ -22,10 +22,11 @@
#include <net/nfc/nci_core.h>
#include "st21nfcb.h"
-#include "ndlc.h"
#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
+#define ST21NFCB_NCI1_X_PROPRIETARY_ISO15693 0x83
+
static int st21nfcb_nci_open(struct nci_dev *ndev)
{
struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
@@ -65,10 +66,18 @@ static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
return ndlc_send(info->ndlc, skb);
}
+static __u32 st21nfcb_nci_get_rfprotocol(struct nci_dev *ndev,
+ __u8 rf_protocol)
+{
+ return rf_protocol == ST21NFCB_NCI1_X_PROPRIETARY_ISO15693 ?
+ NFC_PROTO_ISO15693_MASK : 0;
+}
+
static struct nci_ops st21nfcb_nci_ops = {
.open = st21nfcb_nci_open,
.close = st21nfcb_nci_close,
.send = st21nfcb_nci_send,
+ .get_rfprotocol = st21nfcb_nci_get_rfprotocol,
};
int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
@@ -88,29 +97,25 @@ int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
| NFC_PROTO_FELICA_MASK
| NFC_PROTO_ISO14443_MASK
| NFC_PROTO_ISO14443_B_MASK
+ | NFC_PROTO_ISO15693_MASK
| NFC_PROTO_NFC_DEP_MASK;
ndlc->ndev = nci_allocate_device(&st21nfcb_nci_ops, protocols,
phy_headroom, phy_tailroom);
if (!ndlc->ndev) {
pr_err("Cannot allocate nfc ndev\n");
- r = -ENOMEM;
- goto err_alloc_ndev;
+ return -ENOMEM;
}
info->ndlc = ndlc;
nci_set_drvdata(ndlc->ndev, info);
r = nci_register_device(ndlc->ndev);
- if (r)
- goto err_regdev;
-
- return r;
-err_regdev:
- nci_free_device(ndlc->ndev);
+ if (r) {
+ pr_err("Cannot register nfc device to nci core\n");
+ nci_free_device(ndlc->ndev);
+ }
-err_alloc_ndev:
- kfree(info);
return r;
}
EXPORT_SYMBOL_GPL(st21nfcb_nci_probe);
diff --git a/drivers/nfc/st21nfcb/st21nfcb.h b/drivers/nfc/st21nfcb/st21nfcb.h
index 4bbbebb..ea58a56 100644
--- a/drivers/nfc/st21nfcb/st21nfcb.h
+++ b/drivers/nfc/st21nfcb/st21nfcb.h
@@ -19,8 +19,6 @@
#ifndef __LOCAL_ST21NFCB_H_
#define __LOCAL_ST21NFCB_H_
-#include <net/nfc/nci_core.h>
-
#include "ndlc.h"
/* Define private flags: */
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index 3b78b03..d2ccd28 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c
@@ -36,7 +36,13 @@
* The trf7970a is very timing sensitive and the VIN, EN2, and EN
* pins must asserted in that order and with specific delays in between.
* The delays used in the driver were provided by TI and have been
- * confirmed to work with this driver.
+ * confirmed to work with this driver. There is a bug with the current
+ * version of the trf7970a that requires that EN2 remain low no matter
+ * what. If it goes high, it will generate an RF field even when in
+ * passive target mode. TI has indicated that the chip will work okay
+ * when EN2 is left low. The 'en2-rf-quirk' device tree property
+ * indicates that trf7970a currently being used has the erratum and
+ * that EN2 must be kept low.
*
* Timeouts are implemented using the delayed workqueue kernel facility.
* Timeouts are required so things don't hang when there is no response
@@ -56,7 +62,7 @@
* way to abort a command that's already been sent to the tag is so turn
* off power to the tag. If we do that, though, we'd have to go through
* the entire anticollision procedure again but the digital layer doesn't
- * support that. So, if an abort is received before trf7970a_in_send_cmd()
+ * support that. So, if an abort is received before trf7970a_send_cmd()
* has sent the command to the tag, it simply returns -ECANCELED. If the
* command has already been sent to the tag, then the driver continues
* normally and recieves the response data (or error) but just before
@@ -77,6 +83,13 @@
* been received and there isn't an error). The delay is 20 ms since delays
* of ~16 ms have been observed during testing.
*
+ * When transmitting a frame larger than the FIFO size (127 bytes), the
+ * driver will wait 20 ms for the FIFO to drain past the low-watermark
+ * and generate an interrupt. The low-watermark set to 32 bytes so the
+ * interrupt should fire after 127 - 32 = 95 bytes have been sent. At
+ * the lowest possible bit rate (6.62 kbps for 15693), it will take up
+ * to ~14.35 ms so 20 ms is used for the timeout.
+ *
* Type 2 write and sector select commands respond with a 4-bit ACK or NACK.
* Having only 4 bits in the FIFO won't normally generate an interrupt so
* driver enables the '4_bit_RX' bit of the Special Functions register 1
@@ -99,40 +112,43 @@
* Note under Table 1-1 in section 1.6 of
* http://www.ti.com/lit/ug/scbu011/scbu011.pdf, that wait should be at least
* 10 ms for TI Tag-it HF-I tags; however testing has shown that is not long
- * enough. For this reason, the driver waits 20 ms which seems to work
+ * enough so 20 ms is used. So the timer is set to 40 ms - 20 ms to drain
+ * up to 127 bytes in the FIFO at the lowest bit rate plus another 20 ms to
+ * ensure the wait is long enough before sending the EOF. This seems to work
* reliably.
*/
#define TRF7970A_SUPPORTED_PROTOCOLS \
(NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \
NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_FELICA_MASK | \
- NFC_PROTO_ISO15693_MASK)
+ NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK)
#define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */
-/* TX data must be prefixed with a FIFO reset cmd, a cmd that depends
- * on what the current framing is, the address of the TX length byte 1
- * register (0x1d), and the 2 byte length of the data to be transmitted.
- * That totals 5 bytes.
- */
-#define TRF7970A_TX_SKB_HEADROOM 5
-
#define TRF7970A_RX_SKB_ALLOC_SIZE 256
-#define TRF7970A_FIFO_SIZE 128
+#define TRF7970A_FIFO_SIZE 127
/* TX length is 3 nibbles long ==> 4KB - 1 bytes max */
#define TRF7970A_TX_MAX (4096 - 1)
+#define TRF7970A_WAIT_FOR_TX_IRQ 20
#define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 20
-#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3
-#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20
+#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 20
+#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 40
+
+/* Guard times for various RF technologies (in us) */
+#define TRF7970A_GUARD_TIME_NFCA 5000
+#define TRF7970A_GUARD_TIME_NFCB 5000
+#define TRF7970A_GUARD_TIME_NFCF 20000
+#define TRF7970A_GUARD_TIME_15693 1000
/* Quirks */
/* Erratum: When reading IRQ Status register on trf7970a, we must issue a
* read continuous command for IRQ Status and Collision Position registers.
*/
-#define TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA BIT(0)
+#define TRF7970A_QUIRK_IRQ_STATUS_READ BIT(0)
+#define TRF7970A_QUIRK_EN2_MUST_STAY_LOW BIT(1)
/* Direct commands */
#define TRF7970A_CMD_IDLE 0x00
@@ -149,8 +165,8 @@
#define TRF7970A_CMD_CLOSE_SLOT 0x15
#define TRF7970A_CMD_BLOCK_RX 0x16
#define TRF7970A_CMD_ENABLE_RX 0x17
-#define TRF7970A_CMD_TEST_EXT_RF 0x18
-#define TRF7970A_CMD_TEST_INT_RF 0x19
+#define TRF7970A_CMD_TEST_INT_RF 0x18
+#define TRF7970A_CMD_TEST_EXT_RF 0x19
#define TRF7970A_CMD_RX_GAIN_ADJUST 0x1a
/* Bits determining whether its a direct command or register R/W,
@@ -224,6 +240,15 @@
#define TRF7970A_ISO_CTRL_14443B_848 0x0f
#define TRF7970A_ISO_CTRL_FELICA_212 0x1a
#define TRF7970A_ISO_CTRL_FELICA_424 0x1b
+#define TRF7970A_ISO_CTRL_NFC_NFCA_106 0x01
+#define TRF7970A_ISO_CTRL_NFC_NFCF_212 0x02
+#define TRF7970A_ISO_CTRL_NFC_NFCF_424 0x03
+#define TRF7970A_ISO_CTRL_NFC_CE_14443A 0x00
+#define TRF7970A_ISO_CTRL_NFC_CE_14443B 0x01
+#define TRF7970A_ISO_CTRL_NFC_CE BIT(2)
+#define TRF7970A_ISO_CTRL_NFC_ACTIVE BIT(3)
+#define TRF7970A_ISO_CTRL_NFC_INITIATOR BIT(4)
+#define TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE BIT(5)
#define TRF7970A_ISO_CTRL_RFID BIT(5)
#define TRF7970A_ISO_CTRL_DIR_MODE BIT(6)
#define TRF7970A_ISO_CTRL_RX_CRC_N BIT(7) /* true == No CRC */
@@ -249,12 +274,32 @@
#define TRF7970A_MODULATOR_EN_OOK BIT(6)
#define TRF7970A_MODULATOR_27MHZ BIT(7)
+#define TRF7970A_RX_SPECIAL_SETTINGS_NO_LIM BIT(0)
+#define TRF7970A_RX_SPECIAL_SETTINGS_AGCR BIT(1)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_0DB (0x0 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_5DB (0x1 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_10DB (0x2 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_15DB (0x3 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_HBT BIT(4)
+#define TRF7970A_RX_SPECIAL_SETTINGS_M848 BIT(5)
+#define TRF7970A_RX_SPECIAL_SETTINGS_C424 BIT(6)
+#define TRF7970A_RX_SPECIAL_SETTINGS_C212 BIT(7)
+
+#define TRF7970A_REG_IO_CTRL_VRS(v) ((v) & 0x07)
+#define TRF7970A_REG_IO_CTRL_IO_LOW BIT(5)
+#define TRF7970A_REG_IO_CTRL_EN_EXT_PA BIT(6)
+#define TRF7970A_REG_IO_CTRL_AUTO_REG BIT(7)
+
/* IRQ Status Register Bits */
#define TRF7970A_IRQ_STATUS_NORESP BIT(0) /* ISO15693 only */
+#define TRF7970A_IRQ_STATUS_NFC_COL_ERROR BIT(0)
#define TRF7970A_IRQ_STATUS_COL BIT(1)
#define TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR BIT(2)
+#define TRF7970A_IRQ_STATUS_NFC_RF BIT(2)
#define TRF7970A_IRQ_STATUS_PARITY_ERROR BIT(3)
+#define TRF7970A_IRQ_STATUS_NFC_SDD BIT(3)
#define TRF7970A_IRQ_STATUS_CRC_ERROR BIT(4)
+#define TRF7970A_IRQ_STATUS_NFC_PROTO_ERROR BIT(4)
#define TRF7970A_IRQ_STATUS_FIFO BIT(5)
#define TRF7970A_IRQ_STATUS_SRX BIT(6)
#define TRF7970A_IRQ_STATUS_TX BIT(7)
@@ -265,6 +310,10 @@
TRF7970A_IRQ_STATUS_PARITY_ERROR | \
TRF7970A_IRQ_STATUS_CRC_ERROR)
+#define TRF7970A_RSSI_OSC_STATUS_RSSI_MASK (BIT(2) | BIT(1) | BIT(0))
+#define TRF7970A_RSSI_OSC_STATUS_RSSI_X_MASK (BIT(5) | BIT(4) | BIT(3))
+#define TRF7970A_RSSI_OSC_STATUS_RSSI_OSC_OK BIT(6)
+
#define TRF7970A_SPECIAL_FCN_REG1_COL_7_6 BIT(0)
#define TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL BIT(1)
#define TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX BIT(2)
@@ -281,6 +330,49 @@
#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_16 0x2
#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32 0x3
+#define TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(v) ((v) & 0x07)
+#define TRF7970A_NFC_LOW_FIELD_LEVEL_CLEX_DIS BIT(7)
+
+#define TRF7970A_NFC_TARGET_LEVEL_RFDET(v) ((v) & 0x07)
+#define TRF7970A_NFC_TARGET_LEVEL_HI_RF BIT(3)
+#define TRF7970A_NFC_TARGET_LEVEL_SDD_EN BIT(3)
+#define TRF7970A_NFC_TARGET_LEVEL_LD_S_4BYTES (0x0 << 6)
+#define TRF7970A_NFC_TARGET_LEVEL_LD_S_7BYTES (0x1 << 6)
+#define TRF7970A_NFC_TARGET_LEVEL_LD_S_10BYTES (0x2 << 6)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106 BIT(0)
+#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212 BIT(1)
+#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424 (BIT(0) | BIT(1))
+#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B BIT(2)
+#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 BIT(3)
+#define TRF79070A_NFC_TARGET_PROTOCOL_FELICA BIT(4)
+#define TRF79070A_NFC_TARGET_PROTOCOL_RF_L BIT(6)
+#define TRF79070A_NFC_TARGET_PROTOCOL_RF_H BIT(7)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_106A \
+ (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \
+ TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \
+ TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 | \
+ TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_106B \
+ (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \
+ TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \
+ TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B | \
+ TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_212F \
+ (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \
+ TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \
+ TRF79070A_NFC_TARGET_PROTOCOL_FELICA | \
+ TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_424F \
+ (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \
+ TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \
+ TRF79070A_NFC_TARGET_PROTOCOL_FELICA | \
+ TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424)
+
#define TRF7970A_FIFO_STATUS_OVERFLOW BIT(7)
/* NFC (ISO/IEC 14443A) Type 2 Tag commands */
@@ -317,13 +409,16 @@
(ISO15693_REQ_FLAG_SUB_CARRIER | ISO15693_REQ_FLAG_DATA_RATE)
enum trf7970a_state {
- TRF7970A_ST_OFF,
+ TRF7970A_ST_PWR_OFF,
+ TRF7970A_ST_RF_OFF,
TRF7970A_ST_IDLE,
TRF7970A_ST_IDLE_RX_BLOCKED,
TRF7970A_ST_WAIT_FOR_TX_FIFO,
TRF7970A_ST_WAIT_FOR_RX_DATA,
TRF7970A_ST_WAIT_FOR_RX_DATA_CONT,
TRF7970A_ST_WAIT_TO_ISSUE_EOF,
+ TRF7970A_ST_LISTENING,
+ TRF7970A_ST_LISTENING_MD,
TRF7970A_ST_MAX
};
@@ -334,6 +429,7 @@ struct trf7970a {
struct regulator *regulator;
struct nfc_digital_dev *ddev;
u32 quirks;
+ bool is_initiator;
bool aborting;
struct sk_buff *tx_skb;
struct sk_buff *rx_skb;
@@ -344,8 +440,10 @@ struct trf7970a {
u8 iso_ctrl_tech;
u8 modulator_sys_clk_ctrl;
u8 special_fcn_reg1;
+ unsigned int guard_time;
int technology;
int framing;
+ u8 md_rf_tech;
u8 tx_cmd;
bool issue_eof;
int en2_gpio;
@@ -386,15 +484,28 @@ static int trf7970a_read(struct trf7970a *trf, u8 reg, u8 *val)
return ret;
}
-static int trf7970a_read_cont(struct trf7970a *trf, u8 reg,
- u8 *buf, size_t len)
+static int trf7970a_read_cont(struct trf7970a *trf, u8 reg, u8 *buf, size_t len)
{
u8 addr = reg | TRF7970A_CMD_BIT_RW | TRF7970A_CMD_BIT_CONTINUOUS;
+ struct spi_transfer t[2];
+ struct spi_message m;
int ret;
dev_dbg(trf->dev, "read_cont(0x%x, %zd)\n", addr, len);
- ret = spi_write_then_read(trf->spi, &addr, 1, buf, len);
+ spi_message_init(&m);
+
+ memset(&t, 0, sizeof(t));
+
+ t[0].tx_buf = &addr;
+ t[0].len = sizeof(addr);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+ t[1].len = len;
+ spi_message_add_tail(&t[1], &m);
+
+ ret = spi_sync(trf->spi, &m);
if (ret)
dev_err(trf->dev, "%s - addr: 0x%x, ret: %d\n", __func__, addr,
ret);
@@ -424,7 +535,7 @@ static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status)
addr = TRF7970A_IRQ_STATUS | TRF7970A_CMD_BIT_RW;
- if (trf->quirks & TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA) {
+ if (trf->quirks & TRF7970A_QUIRK_IRQ_STATUS_READ) {
addr |= TRF7970A_CMD_BIT_CONTINUOUS;
ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2);
} else {
@@ -440,10 +551,60 @@ static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status)
return ret;
}
-static void trf7970a_send_upstream(struct trf7970a *trf)
+static int trf7970a_read_target_proto(struct trf7970a *trf, u8 *target_proto)
{
- u8 rssi;
+ int ret;
+ u8 buf[2];
+ u8 addr;
+ addr = TRF79070A_NFC_TARGET_PROTOCOL | TRF7970A_CMD_BIT_RW |
+ TRF7970A_CMD_BIT_CONTINUOUS;
+
+ ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2);
+ if (ret)
+ dev_err(trf->dev, "%s - target_proto: Read failed: %d\n",
+ __func__, ret);
+ else
+ *target_proto = buf[0];
+
+ return ret;
+}
+
+static int trf7970a_mode_detect(struct trf7970a *trf, u8 *rf_tech)
+{
+ int ret;
+ u8 target_proto, tech;
+
+ ret = trf7970a_read_target_proto(trf, &target_proto);
+ if (ret)
+ return ret;
+
+ switch (target_proto) {
+ case TRF79070A_NFC_TARGET_PROTOCOL_106A:
+ tech = NFC_DIGITAL_RF_TECH_106A;
+ break;
+ case TRF79070A_NFC_TARGET_PROTOCOL_106B:
+ tech = NFC_DIGITAL_RF_TECH_106B;
+ break;
+ case TRF79070A_NFC_TARGET_PROTOCOL_212F:
+ tech = NFC_DIGITAL_RF_TECH_212F;
+ break;
+ case TRF79070A_NFC_TARGET_PROTOCOL_424F:
+ tech = NFC_DIGITAL_RF_TECH_424F;
+ break;
+ default:
+ dev_dbg(trf->dev, "%s - mode_detect: target_proto: 0x%x\n",
+ __func__, target_proto);
+ return -EIO;
+ }
+
+ *rf_tech = tech;
+
+ return ret;
+}
+
+static void trf7970a_send_upstream(struct trf7970a *trf)
+{
dev_kfree_skb_any(trf->tx_skb);
trf->tx_skb = NULL;
@@ -452,13 +613,6 @@ static void trf7970a_send_upstream(struct trf7970a *trf)
16, 1, trf->rx_skb->data, trf->rx_skb->len,
false);
- /* According to the manual it is "good form" to reset the fifo and
- * read the RSSI levels & oscillator status register here. It doesn't
- * explain why.
- */
- trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);
- trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi);
-
trf->state = TRF7970A_ST_IDLE;
if (trf->aborting) {
@@ -481,6 +635,8 @@ static void trf7970a_send_err_upstream(struct trf7970a *trf, int errno)
{
dev_dbg(trf->dev, "Error - state: %d, errno: %d\n", trf->state, errno);
+ cancel_delayed_work(&trf->timeout_work);
+
kfree_skb(trf->rx_skb);
trf->rx_skb = ERR_PTR(errno);
@@ -488,15 +644,29 @@ static void trf7970a_send_err_upstream(struct trf7970a *trf, int errno)
}
static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb,
- unsigned int len)
+ unsigned int len, u8 *prefix, unsigned int prefix_len)
{
+ struct spi_transfer t[2];
+ struct spi_message m;
unsigned int timeout;
int ret;
print_hex_dump_debug("trf7970a tx data: ", DUMP_PREFIX_NONE,
16, 1, skb->data, len, false);
- ret = spi_write(trf->spi, skb->data, len);
+ spi_message_init(&m);
+
+ memset(&t, 0, sizeof(t));
+
+ t[0].tx_buf = prefix;
+ t[0].len = prefix_len;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = skb->data;
+ t[1].len = len;
+ spi_message_add_tail(&t[1], &m);
+
+ ret = spi_sync(trf->spi, &m);
if (ret) {
dev_err(trf->dev, "%s - Can't send tx data: %d\n", __func__,
ret);
@@ -514,7 +684,11 @@ static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb,
timeout = TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF;
} else {
trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA;
- timeout = trf->timeout;
+
+ if (!trf->timeout)
+ timeout = TRF7970A_WAIT_FOR_TX_IRQ;
+ else
+ timeout = trf->timeout;
}
}
@@ -532,6 +706,7 @@ static void trf7970a_fill_fifo(struct trf7970a *trf)
unsigned int len;
int ret;
u8 fifo_bytes;
+ u8 prefix;
ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes);
if (ret) {
@@ -541,18 +716,21 @@ static void trf7970a_fill_fifo(struct trf7970a *trf)
dev_dbg(trf->dev, "Filling FIFO - fifo_bytes: 0x%x\n", fifo_bytes);
- if (fifo_bytes & TRF7970A_FIFO_STATUS_OVERFLOW) {
- dev_err(trf->dev, "%s - fifo overflow: 0x%x\n", __func__,
- fifo_bytes);
- trf7970a_send_err_upstream(trf, -EIO);
- return;
- }
+ fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW;
/* Calculate how much more data can be written to the fifo */
len = TRF7970A_FIFO_SIZE - fifo_bytes;
+ if (!len) {
+ schedule_delayed_work(&trf->timeout_work,
+ msecs_to_jiffies(TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT));
+ return;
+ }
+
len = min(skb->len, len);
- ret = trf7970a_transmit(trf, skb, len);
+ prefix = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_FIFO_IO_REGISTER;
+
+ ret = trf7970a_transmit(trf, skb, len, &prefix, sizeof(prefix));
if (ret)
trf7970a_send_err_upstream(trf, ret);
}
@@ -576,16 +754,11 @@ static void trf7970a_drain_fifo(struct trf7970a *trf, u8 status)
dev_dbg(trf->dev, "Draining FIFO - fifo_bytes: 0x%x\n", fifo_bytes);
+ fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW;
+
if (!fifo_bytes)
goto no_rx_data;
- if (fifo_bytes & TRF7970A_FIFO_STATUS_OVERFLOW) {
- dev_err(trf->dev, "%s - fifo overflow: 0x%x\n", __func__,
- fifo_bytes);
- trf7970a_send_err_upstream(trf, -EIO);
- return;
- }
-
if (fifo_bytes > skb_tailroom(skb)) {
skb = skb_copy_expand(skb, skb_headroom(skb),
max_t(int, fifo_bytes,
@@ -615,6 +788,21 @@ static void trf7970a_drain_fifo(struct trf7970a *trf, u8 status)
status = TRF7970A_IRQ_STATUS_SRX;
} else {
trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA_CONT;
+
+ ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes);
+ if (ret) {
+ trf7970a_send_err_upstream(trf, ret);
+ return;
+ }
+
+ fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW;
+
+ /* If there are bytes in the FIFO, set status to '0' so
+ * the if stmt below doesn't fire and the driver will wait
+ * for the trf7970a to generate another RX interrupt.
+ */
+ if (fifo_bytes)
+ status = 0;
}
no_rx_data:
@@ -634,11 +822,11 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
{
struct trf7970a *trf = dev_id;
int ret;
- u8 status;
+ u8 status, fifo_bytes, iso_ctrl;
mutex_lock(&trf->lock);
- if (trf->state == TRF7970A_ST_OFF) {
+ if (trf->state == TRF7970A_ST_RF_OFF) {
mutex_unlock(&trf->lock);
return IRQ_NONE;
}
@@ -660,12 +848,12 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
switch (trf->state) {
case TRF7970A_ST_IDLE:
case TRF7970A_ST_IDLE_RX_BLOCKED:
- /* If getting interrupts caused by RF noise, turn off the
- * receiver to avoid unnecessary interrupts. It will be
- * turned back on in trf7970a_in_send_cmd() when the next
- * command is issued.
+ /* If initiator and getting interrupts caused by RF noise,
+ * turn off the receiver to avoid unnecessary interrupts.
+ * It will be turned back on in trf7970a_send_cmd() when
+ * the next command is issued.
*/
- if (status & TRF7970A_IRQ_STATUS_ERROR) {
+ if (trf->is_initiator && (status & TRF7970A_IRQ_STATUS_ERROR)) {
trf7970a_cmd(trf, TRF7970A_CMD_BLOCK_RX);
trf->state = TRF7970A_ST_IDLE_RX_BLOCKED;
}
@@ -687,8 +875,68 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
trf->ignore_timeout =
!cancel_delayed_work(&trf->timeout_work);
trf7970a_drain_fifo(trf, status);
- } else if (status == TRF7970A_IRQ_STATUS_TX) {
+ } else if (status & TRF7970A_IRQ_STATUS_FIFO) {
+ ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS,
+ &fifo_bytes);
+
+ fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW;
+
+ if (ret)
+ trf7970a_send_err_upstream(trf, ret);
+ else if (!fifo_bytes)
+ trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);
+ } else if ((status == TRF7970A_IRQ_STATUS_TX) ||
+ (!trf->is_initiator &&
+ (status == (TRF7970A_IRQ_STATUS_TX |
+ TRF7970A_IRQ_STATUS_NFC_RF)))) {
trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);
+
+ if (!trf->timeout) {
+ trf->ignore_timeout = !cancel_delayed_work(
+ &trf->timeout_work);
+ trf->rx_skb = ERR_PTR(0);
+ trf7970a_send_upstream(trf);
+ break;
+ }
+
+ if (trf->is_initiator)
+ break;
+
+ iso_ctrl = trf->iso_ctrl;
+
+ switch (trf->framing) {
+ case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
+ trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC;
+ iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;
+ trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */
+ break;
+ case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
+ trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
+ iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
+ trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */
+ break;
+ case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE:
+ ret = trf7970a_write(trf,
+ TRF7970A_SPECIAL_FCN_REG1,
+ TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL);
+ if (ret)
+ goto err_unlock_exit;
+
+ trf->special_fcn_reg1 =
+ TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL;
+ break;
+ default:
+ break;
+ }
+
+ if (iso_ctrl != trf->iso_ctrl) {
+ ret = trf7970a_write(trf, TRF7970A_ISO_CTRL,
+ iso_ctrl);
+ if (ret)
+ goto err_unlock_exit;
+
+ trf->iso_ctrl = iso_ctrl;
+ }
} else {
trf7970a_send_err_upstream(trf, -EIO);
}
@@ -697,11 +945,37 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
if (status != TRF7970A_IRQ_STATUS_TX)
trf7970a_send_err_upstream(trf, -EIO);
break;
+ case TRF7970A_ST_LISTENING:
+ if (status & TRF7970A_IRQ_STATUS_SRX) {
+ trf->ignore_timeout =
+ !cancel_delayed_work(&trf->timeout_work);
+ trf7970a_drain_fifo(trf, status);
+ } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) {
+ trf7970a_send_err_upstream(trf, -EIO);
+ }
+ break;
+ case TRF7970A_ST_LISTENING_MD:
+ if (status & TRF7970A_IRQ_STATUS_SRX) {
+ trf->ignore_timeout =
+ !cancel_delayed_work(&trf->timeout_work);
+
+ ret = trf7970a_mode_detect(trf, &trf->md_rf_tech);
+ if (ret) {
+ trf7970a_send_err_upstream(trf, ret);
+ } else {
+ trf->state = TRF7970A_ST_LISTENING;
+ trf7970a_drain_fifo(trf, status);
+ }
+ } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) {
+ trf7970a_send_err_upstream(trf, -EIO);
+ }
+ break;
default:
dev_err(trf->dev, "%s - Driver in invalid state: %d\n",
__func__, trf->state);
}
+err_unlock_exit:
mutex_unlock(&trf->lock);
return IRQ_HANDLED;
}
@@ -742,7 +1016,7 @@ static void trf7970a_timeout_work_handler(struct work_struct *work)
if (trf->ignore_timeout)
trf->ignore_timeout = false;
else if (trf->state == TRF7970A_ST_WAIT_FOR_RX_DATA_CONT)
- trf7970a_send_upstream(trf); /* No more rx data so send up */
+ trf7970a_drain_fifo(trf, TRF7970A_IRQ_STATUS_SRX);
else if (trf->state == TRF7970A_ST_WAIT_TO_ISSUE_EOF)
trf7970a_issue_eof(trf);
else
@@ -765,11 +1039,16 @@ static int trf7970a_init(struct trf7970a *trf)
if (ret)
goto err_out;
- /* Must clear NFC Target Detection Level reg due to erratum */
- ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0);
+ usleep_range(1000, 2000);
+
+ trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON;
+
+ ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 0);
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);
@@ -792,6 +1071,10 @@ err_out:
static void trf7970a_switch_rf_off(struct trf7970a *trf)
{
+ if ((trf->state == TRF7970A_ST_PWR_OFF) ||
+ (trf->state == TRF7970A_ST_RF_OFF))
+ return;
+
dev_dbg(trf->dev, "Switching rf off\n");
trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON;
@@ -799,24 +1082,41 @@ static void trf7970a_switch_rf_off(struct trf7970a *trf)
trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl);
trf->aborting = false;
- trf->state = TRF7970A_ST_OFF;
+ trf->state = TRF7970A_ST_RF_OFF;
pm_runtime_mark_last_busy(trf->dev);
pm_runtime_put_autosuspend(trf->dev);
}
-static void trf7970a_switch_rf_on(struct trf7970a *trf)
+static int trf7970a_switch_rf_on(struct trf7970a *trf)
{
+ int ret;
+
dev_dbg(trf->dev, "Switching rf on\n");
pm_runtime_get_sync(trf->dev);
+ if (trf->state != TRF7970A_ST_RF_OFF) { /* Power on, RF off */
+ dev_err(trf->dev, "%s - Incorrect state: %d\n", __func__,
+ trf->state);
+ return -EINVAL;
+ }
+
+ ret = trf7970a_init(trf);
+ if (ret) {
+ dev_err(trf->dev, "%s - Can't initialize: %d\n", __func__, ret);
+ return ret;
+ }
+
trf->state = TRF7970A_ST_IDLE;
+
+ return 0;
}
static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+ int ret = 0;
dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on);
@@ -824,8 +1124,9 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on)
if (on) {
switch (trf->state) {
- case TRF7970A_ST_OFF:
- trf7970a_switch_rf_on(trf);
+ case TRF7970A_ST_PWR_OFF:
+ case TRF7970A_ST_RF_OFF:
+ ret = trf7970a_switch_rf_on(trf);
break;
case TRF7970A_ST_IDLE:
case TRF7970A_ST_IDLE_RX_BLOCKED:
@@ -834,26 +1135,31 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on)
dev_err(trf->dev, "%s - Invalid request: %d %d\n",
__func__, trf->state, on);
trf7970a_switch_rf_off(trf);
+ ret = -EINVAL;
}
} else {
switch (trf->state) {
- case TRF7970A_ST_OFF:
+ case TRF7970A_ST_PWR_OFF:
+ case TRF7970A_ST_RF_OFF:
break;
default:
dev_err(trf->dev, "%s - Invalid request: %d %d\n",
__func__, trf->state, on);
+ ret = -EINVAL;
/* FALLTHROUGH */
case TRF7970A_ST_IDLE:
case TRF7970A_ST_IDLE_RX_BLOCKED:
+ case TRF7970A_ST_WAIT_FOR_RX_DATA:
+ case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
trf7970a_switch_rf_off(trf);
}
}
mutex_unlock(&trf->lock);
- return 0;
+ return ret;
}
-static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech)
+static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech)
{
int ret = 0;
@@ -863,22 +1169,27 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int 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->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->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->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->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->guard_time = TRF7970A_GUARD_TIME_15693;
break;
default:
dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);
@@ -887,12 +1198,54 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech)
trf->technology = tech;
+ /* If in initiator mode and not changing the RF tech due to a
+ * PSL sequence (indicated by 'trf->iso_ctrl == 0xff' from
+ * trf7970a_init()), clear the NFC Target Detection Level register
+ * due to erratum.
+ */
+ if (trf->iso_ctrl == 0xff)
+ ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0);
+
return ret;
}
-static int trf7970a_config_framing(struct trf7970a *trf, int framing)
+static int trf7970a_is_rf_field(struct trf7970a *trf, bool *is_rf_field)
+{
+ int ret;
+ u8 rssi;
+
+ ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,
+ trf->chip_status_ctrl | TRF7970A_CHIP_STATUS_REC_ON);
+ if (ret)
+ return ret;
+
+ ret = trf7970a_cmd(trf, TRF7970A_CMD_TEST_EXT_RF);
+ if (ret)
+ return ret;
+
+ usleep_range(50, 60);
+
+ ret = trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi);
+ if (ret)
+ return ret;
+
+ ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,
+ trf->chip_status_ctrl);
+ if (ret)
+ return ret;
+
+ if (rssi & TRF7970A_RSSI_OSC_STATUS_RSSI_MASK)
+ *is_rf_field = true;
+ else
+ *is_rf_field = false;
+
+ return 0;
+}
+
+static int trf7970a_in_config_framing(struct trf7970a *trf, int framing)
{
u8 iso_ctrl = trf->iso_ctrl_tech;
+ bool is_rf_field = false;
int ret;
dev_dbg(trf->dev, "framing: %d\n", framing);
@@ -911,6 +1264,8 @@ static int trf7970a_config_framing(struct trf7970a *trf, int framing)
case NFC_DIGITAL_FRAMING_NFCF_T3T:
case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
case NFC_DIGITAL_FRAMING_ISO15693_T5T:
+ case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
+ case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP:
trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
break;
@@ -925,6 +1280,15 @@ static int trf7970a_config_framing(struct trf7970a *trf, int framing)
trf->framing = framing;
+ if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) {
+ ret = trf7970a_is_rf_field(trf, &is_rf_field);
+ if (ret)
+ return ret;
+
+ if (is_rf_field)
+ return -EBUSY;
+ }
+
if (iso_ctrl != trf->iso_ctrl) {
ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl);
if (ret)
@@ -947,7 +1311,7 @@ static int trf7970a_config_framing(struct trf7970a *trf, int framing)
trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON;
- usleep_range(5000, 6000);
+ usleep_range(trf->guard_time, trf->guard_time + 1000);
}
return 0;
@@ -963,21 +1327,28 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type,
mutex_lock(&trf->lock);
- if (trf->state == TRF7970A_ST_OFF)
- trf7970a_switch_rf_on(trf);
+ trf->is_initiator = true;
+
+ if ((trf->state == TRF7970A_ST_PWR_OFF) ||
+ (trf->state == TRF7970A_ST_RF_OFF)) {
+ ret = trf7970a_switch_rf_on(trf);
+ if (ret)
+ goto err_unlock;
+ }
switch (type) {
case NFC_DIGITAL_CONFIG_RF_TECH:
- ret = trf7970a_config_rf_tech(trf, param);
+ ret = trf7970a_in_config_rf_tech(trf, param);
break;
case NFC_DIGITAL_CONFIG_FRAMING:
- ret = trf7970a_config_framing(trf, param);
+ ret = trf7970a_in_config_framing(trf, param);
break;
default:
dev_dbg(trf->dev, "Unknown type: %d\n", type);
ret = -EINVAL;
}
+err_unlock:
mutex_unlock(&trf->lock);
return ret;
}
@@ -1067,14 +1438,15 @@ static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
return 0;
}
-static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
+static int trf7970a_send_cmd(struct nfc_digital_dev *ddev,
struct sk_buff *skb, u16 timeout,
nfc_digital_cmd_complete_t cb, void *arg)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
- char *prefix;
+ u8 prefix[5];
unsigned int len;
int ret;
+ u8 status;
dev_dbg(trf->dev, "New request - state: %d, timeout: %d ms, len: %d\n",
trf->state, timeout, skb->len);
@@ -1099,12 +1471,14 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
goto out_err;
}
- trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
- GFP_KERNEL);
- if (!trf->rx_skb) {
- dev_dbg(trf->dev, "Can't alloc rx_skb\n");
- ret = -ENOMEM;
- goto out_err;
+ if (timeout) {
+ trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
+ GFP_KERNEL);
+ if (!trf->rx_skb) {
+ dev_dbg(trf->dev, "Can't alloc rx_skb\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
}
if (trf->state == TRF7970A_ST_IDLE_RX_BLOCKED) {
@@ -1115,9 +1489,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
trf->state = TRF7970A_ST_IDLE;
}
- ret = trf7970a_per_cmd_config(trf, skb);
- if (ret)
- goto out_err;
+ if (trf->is_initiator) {
+ ret = trf7970a_per_cmd_config(trf, skb);
+ if (ret)
+ goto out_err;
+ }
trf->ddev = ddev;
trf->tx_skb = skb;
@@ -1127,11 +1503,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
trf->ignore_timeout = false;
len = skb->len;
- prefix = skb_push(skb, TRF7970A_TX_SKB_HEADROOM);
/* TX data must be prefixed with a FIFO reset cmd, a cmd that depends
* on what the current framing is, the address of the TX length byte 1
* register (0x1d), and the 2 byte length of the data to be transmitted.
+ * That totals 5 bytes.
*/
prefix[0] = TRF7970A_CMD_BIT_CTRL |
TRF7970A_CMD_BIT_OPCODE(TRF7970A_CMD_FIFO_RESET);
@@ -1150,9 +1526,12 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
len = min_t(int, skb->len, TRF7970A_FIFO_SIZE);
- usleep_range(1000, 2000);
+ /* Clear possible spurious interrupt */
+ ret = trf7970a_read_irqstatus(trf, &status);
+ if (ret)
+ goto out_err;
- ret = trf7970a_transmit(trf, skb, len);
+ ret = trf7970a_transmit(trf, skb, len, prefix, sizeof(prefix));
if (ret) {
kfree_skb(trf->rx_skb);
trf->rx_skb = NULL;
@@ -1163,46 +1542,272 @@ out_err:
return ret;
}
-static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev,
- int type, int param)
+static int trf7970a_tg_config_rf_tech(struct trf7970a *trf, int tech)
+{
+ int ret = 0;
+
+ dev_dbg(trf->dev, "rf technology: %d\n", tech);
+
+ switch (tech) {
+ case NFC_DIGITAL_RF_TECH_106A:
+ 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;
+ 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;
+ 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;
+ break;
+ default:
+ dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);
+ return -EINVAL;
+ }
+
+ trf->technology = tech;
+
+ /* Normally we write the ISO_CTRL register in
+ * trf7970a_tg_config_framing() because the framing can change
+ * the value written. However, when sending a PSL RES,
+ * digital_tg_send_psl_res_complete() doesn't call
+ * trf7970a_tg_config_framing() so we must write the register
+ * here.
+ */
+ if ((trf->framing == NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED) &&
+ (trf->iso_ctrl_tech != trf->iso_ctrl)) {
+ ret = trf7970a_write(trf, TRF7970A_ISO_CTRL,
+ trf->iso_ctrl_tech);
+
+ trf->iso_ctrl = trf->iso_ctrl_tech;
+ }
+
+ return ret;
+}
+
+/* Since this is a target routine, several of the framing calls are
+ * made between receiving the request and sending the response so they
+ * should take effect until after the response is sent. This is accomplished
+ * by skipping the ISO_CTRL register write here and doing it in the interrupt
+ * handler.
+ */
+static int trf7970a_tg_config_framing(struct trf7970a *trf, int framing)
+{
+ u8 iso_ctrl = trf->iso_ctrl_tech;
+ int ret;
+
+ dev_dbg(trf->dev, "framing: %d\n", framing);
+
+ switch (framing) {
+ case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
+ trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC;
+ iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;
+ break;
+ case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
+ case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
+ case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE:
+ /* These ones are applied in the interrupt handler */
+ iso_ctrl = trf->iso_ctrl; /* Don't write to ISO_CTRL yet */
+ break;
+ case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP:
+ trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
+ iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
+ break;
+ case NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED:
+ trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
+ iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
+ break;
+ default:
+ dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing);
+ return -EINVAL;
+ }
+
+ trf->framing = framing;
+
+ if (iso_ctrl != trf->iso_ctrl) {
+ ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl);
+ if (ret)
+ return ret;
+
+ trf->iso_ctrl = iso_ctrl;
+
+ ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL,
+ trf->modulator_sys_clk_ctrl);
+ if (ret)
+ return ret;
+ }
+
+ if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) {
+ ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,
+ trf->chip_status_ctrl |
+ TRF7970A_CHIP_STATUS_RF_ON);
+ if (ret)
+ return ret;
+
+ trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON;
+ }
+
+ return 0;
+}
+
+static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev, int type,
+ int param)
+{
+ struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+ int ret;
+
+ dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param);
+
+ mutex_lock(&trf->lock);
+
+ trf->is_initiator = false;
+
+ if ((trf->state == TRF7970A_ST_PWR_OFF) ||
+ (trf->state == TRF7970A_ST_RF_OFF)) {
+ ret = trf7970a_switch_rf_on(trf);
+ if (ret)
+ goto err_unlock;
+ }
+
+ switch (type) {
+ case NFC_DIGITAL_CONFIG_RF_TECH:
+ ret = trf7970a_tg_config_rf_tech(trf, param);
+ break;
+ case NFC_DIGITAL_CONFIG_FRAMING:
+ ret = trf7970a_tg_config_framing(trf, param);
+ break;
+ default:
+ dev_dbg(trf->dev, "Unknown type: %d\n", type);
+ ret = -EINVAL;
+ }
+
+err_unlock:
+ mutex_unlock(&trf->lock);
+ return ret;
+}
+
+static int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
+ nfc_digital_cmd_complete_t cb, void *arg, bool mode_detect)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+ int ret;
+
+ mutex_lock(&trf->lock);
- dev_dbg(trf->dev, "Unsupported interface\n");
+ if ((trf->state != TRF7970A_ST_IDLE) &&
+ (trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) {
+ dev_err(trf->dev, "%s - Bogus state: %d\n", __func__,
+ trf->state);
+ ret = -EIO;
+ goto out_err;
+ }
- return -EINVAL;
+ if (trf->aborting) {
+ dev_dbg(trf->dev, "Abort process complete\n");
+ trf->aborting = false;
+ ret = -ECANCELED;
+ goto out_err;
+ }
+
+ trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
+ GFP_KERNEL);
+ if (!trf->rx_skb) {
+ dev_dbg(trf->dev, "Can't alloc rx_skb\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ ret = trf7970a_write(trf, TRF7970A_RX_SPECIAL_SETTINGS,
+ TRF7970A_RX_SPECIAL_SETTINGS_HBT |
+ TRF7970A_RX_SPECIAL_SETTINGS_M848 |
+ TRF7970A_RX_SPECIAL_SETTINGS_C424 |
+ TRF7970A_RX_SPECIAL_SETTINGS_C212);
+ if (ret)
+ goto out_err;
+
+ ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL,
+ TRF7970A_REG_IO_CTRL_VRS(0x1));
+ if (ret)
+ goto out_err;
+
+ ret = trf7970a_write(trf, TRF7970A_NFC_LOW_FIELD_LEVEL,
+ TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(0x3));
+ if (ret)
+ goto out_err;
+
+ ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL,
+ TRF7970A_NFC_TARGET_LEVEL_RFDET(0x7));
+ if (ret)
+ goto out_err;
+
+ trf->ddev = ddev;
+ trf->cb = cb;
+ trf->cb_arg = arg;
+ trf->timeout = timeout;
+ trf->ignore_timeout = false;
+
+ ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX);
+ if (ret)
+ goto out_err;
+
+ trf->state = mode_detect ? TRF7970A_ST_LISTENING_MD :
+ TRF7970A_ST_LISTENING;
+
+ schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout));
+
+out_err:
+ mutex_unlock(&trf->lock);
+ return ret;
}
-static int trf7970a_tg_send_cmd(struct nfc_digital_dev *ddev,
- struct sk_buff *skb, u16 timeout,
+static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
nfc_digital_cmd_complete_t cb, void *arg)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
- dev_dbg(trf->dev, "Unsupported interface\n");
+ dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n",
+ trf->state, timeout);
- return -EINVAL;
+ return _trf7970a_tg_listen(ddev, timeout, cb, arg, false);
}
-static int trf7970a_tg_listen(struct nfc_digital_dev *ddev,
+static int trf7970a_tg_listen_md(struct nfc_digital_dev *ddev,
u16 timeout, nfc_digital_cmd_complete_t cb, void *arg)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+ int ret;
+
+ dev_dbg(trf->dev, "Listen MD - state: %d, timeout: %d ms\n",
+ trf->state, timeout);
- dev_dbg(trf->dev, "Unsupported interface\n");
+ ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
+ NFC_DIGITAL_RF_TECH_106A);
+ if (ret)
+ return ret;
- return -EINVAL;
+ ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
+ NFC_DIGITAL_FRAMING_NFCA_NFC_DEP);
+ if (ret)
+ return ret;
+
+ return _trf7970a_tg_listen(ddev, timeout, cb, arg, true);
}
-static int trf7970a_tg_listen_mdaa(struct nfc_digital_dev *ddev,
- struct digital_tg_mdaa_params *mdaa_params,
- u16 timeout, nfc_digital_cmd_complete_t cb, void *arg)
+static int trf7970a_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
- dev_dbg(trf->dev, "Unsupported interface\n");
+ dev_dbg(trf->dev, "Get RF Tech - state: %d, rf_tech: %d\n",
+ trf->state, trf->md_rf_tech);
- return -EINVAL;
+ *rf_tech = trf->md_rf_tech;
+
+ return 0;
}
static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
@@ -1220,6 +1825,11 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
trf->aborting = true;
break;
+ case TRF7970A_ST_LISTENING:
+ trf->ignore_timeout = !cancel_delayed_work(&trf->timeout_work);
+ trf7970a_send_err_upstream(trf, -ECANCELED);
+ dev_dbg(trf->dev, "Abort process complete\n");
+ break;
default:
break;
}
@@ -1229,15 +1839,114 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
static struct nfc_digital_ops trf7970a_nfc_ops = {
.in_configure_hw = trf7970a_in_configure_hw,
- .in_send_cmd = trf7970a_in_send_cmd,
+ .in_send_cmd = trf7970a_send_cmd,
.tg_configure_hw = trf7970a_tg_configure_hw,
- .tg_send_cmd = trf7970a_tg_send_cmd,
+ .tg_send_cmd = trf7970a_send_cmd,
.tg_listen = trf7970a_tg_listen,
- .tg_listen_mdaa = trf7970a_tg_listen_mdaa,
+ .tg_listen_md = trf7970a_tg_listen_md,
+ .tg_get_rf_tech = trf7970a_tg_get_rf_tech,
.switch_rf = trf7970a_switch_rf,
.abort_cmd = trf7970a_abort_cmd,
};
+static int trf7970a_power_up(struct trf7970a *trf)
+{
+ int ret;
+
+ dev_dbg(trf->dev, "Powering up - state: %d\n", trf->state);
+
+ if (trf->state != TRF7970A_ST_PWR_OFF)
+ return 0;
+
+ ret = regulator_enable(trf->regulator);
+ if (ret) {
+ dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
+ return ret;
+ }
+
+ usleep_range(5000, 6000);
+
+ if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) {
+ gpio_set_value(trf->en2_gpio, 1);
+ usleep_range(1000, 2000);
+ }
+
+ gpio_set_value(trf->en_gpio, 1);
+
+ usleep_range(20000, 21000);
+
+ trf->state = TRF7970A_ST_RF_OFF;
+
+ return 0;
+}
+
+static int trf7970a_power_down(struct trf7970a *trf)
+{
+ int ret;
+
+ dev_dbg(trf->dev, "Powering down - state: %d\n", trf->state);
+
+ if (trf->state == TRF7970A_ST_PWR_OFF)
+ return 0;
+
+ if (trf->state != TRF7970A_ST_RF_OFF) {
+ dev_dbg(trf->dev, "Can't power down - not RF_OFF state (%d)\n",
+ trf->state);
+ return -EBUSY;
+ }
+
+ gpio_set_value(trf->en_gpio, 0);
+ gpio_set_value(trf->en2_gpio, 0);
+
+ ret = regulator_disable(trf->regulator);
+ if (ret)
+ dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
+ ret);
+
+ trf->state = TRF7970A_ST_PWR_OFF;
+
+ return ret;
+}
+
+static int trf7970a_startup(struct trf7970a *trf)
+{
+ int ret;
+
+ ret = trf7970a_power_up(trf);
+ if (ret)
+ return ret;
+
+ pm_runtime_set_active(trf->dev);
+ pm_runtime_enable(trf->dev);
+ pm_runtime_mark_last_busy(trf->dev);
+
+ return 0;
+}
+
+static void trf7970a_shutdown(struct trf7970a *trf)
+{
+ switch (trf->state) {
+ case TRF7970A_ST_WAIT_FOR_TX_FIFO:
+ case TRF7970A_ST_WAIT_FOR_RX_DATA:
+ case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
+ case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
+ case TRF7970A_ST_LISTENING:
+ trf7970a_send_err_upstream(trf, -ECANCELED);
+ /* FALLTHROUGH */
+ case TRF7970A_ST_IDLE:
+ case TRF7970A_ST_IDLE_RX_BLOCKED:
+ trf7970a_switch_rf_off(trf);
+ break;
+ default:
+ break;
+ }
+
+ pm_runtime_disable(trf->dev);
+ pm_runtime_set_suspended(trf->dev);
+
+ trf7970a_power_down(trf);
+}
+
static int trf7970a_get_autosuspend_delay(struct device_node *np)
{
int autosuspend_delay, ret;
@@ -1246,15 +1955,18 @@ static int trf7970a_get_autosuspend_delay(struct device_node *np)
if (ret)
autosuspend_delay = TRF7970A_AUTOSUSPEND_DELAY;
- of_node_put(np);
-
return autosuspend_delay;
}
+static int trf7970a_get_vin_voltage_override(struct device_node *np,
+ u32 *vin_uvolts)
+{
+ return of_property_read_u32(np, "vin-voltage-override", vin_uvolts);
+}
+
static int trf7970a_probe(struct spi_device *spi)
{
struct device_node *np = spi->dev.of_node;
- const struct spi_device_id *id = spi_get_device_id(spi);
struct trf7970a *trf;
int uvolts, autosuspend_delay, ret;
@@ -1267,14 +1979,22 @@ static int trf7970a_probe(struct spi_device *spi)
if (!trf)
return -ENOMEM;
- trf->state = TRF7970A_ST_OFF;
+ trf->state = TRF7970A_ST_PWR_OFF;
trf->dev = &spi->dev;
trf->spi = spi;
- trf->quirks = id->driver_data;
spi->mode = SPI_MODE_1;
spi->bits_per_word = 8;
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ dev_err(trf->dev, "Can't set up SPI Communication\n");
+ return ret;
+ }
+
+ if (of_property_read_bool(np, "irq-status-read-quirk"))
+ trf->quirks |= TRF7970A_QUIRK_IRQ_STATUS_READ;
+
/* There are two enable pins - both must be present */
trf->en_gpio = of_get_named_gpio(np, "ti,enable-gpios", 0);
if (!gpio_is_valid(trf->en_gpio)) {
@@ -1283,7 +2003,7 @@ static int trf7970a_probe(struct spi_device *spi)
}
ret = devm_gpio_request_one(trf->dev, trf->en_gpio,
- GPIOF_DIR_OUT | GPIOF_INIT_LOW, "EN");
+ GPIOF_DIR_OUT | GPIOF_INIT_LOW, "trf7970a EN");
if (ret) {
dev_err(trf->dev, "Can't request EN GPIO: %d\n", ret);
return ret;
@@ -1296,12 +2016,15 @@ static int trf7970a_probe(struct spi_device *spi)
}
ret = devm_gpio_request_one(trf->dev, trf->en2_gpio,
- GPIOF_DIR_OUT | GPIOF_INIT_LOW, "EN2");
+ GPIOF_DIR_OUT | GPIOF_INIT_LOW, "trf7970a EN2");
if (ret) {
dev_err(trf->dev, "Can't request EN2 GPIO: %d\n", ret);
return ret;
}
+ if (of_property_read_bool(np, "en2-rf-quirk"))
+ trf->quirks |= TRF7970A_QUIRK_EN2_MUST_STAY_LOW;
+
ret = devm_request_threaded_irq(trf->dev, spi->irq, NULL,
trf7970a_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"trf7970a", trf);
@@ -1326,15 +2049,17 @@ static int trf7970a_probe(struct spi_device *spi)
goto err_destroy_lock;
}
- uvolts = regulator_get_voltage(trf->regulator);
+ ret = trf7970a_get_vin_voltage_override(np, &uvolts);
+ if (ret)
+ uvolts = regulator_get_voltage(trf->regulator);
if (uvolts > 4000000)
trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops,
TRF7970A_SUPPORTED_PROTOCOLS,
- NFC_DIGITAL_DRV_CAPS_IN_CRC, TRF7970A_TX_SKB_HEADROOM,
- 0);
+ NFC_DIGITAL_DRV_CAPS_IN_CRC |
+ NFC_DIGITAL_DRV_CAPS_TG_CRC, 0, 0);
if (!trf->ddev) {
dev_err(trf->dev, "Can't allocate NFC digital device\n");
ret = -ENOMEM;
@@ -1349,19 +2074,23 @@ static int trf7970a_probe(struct spi_device *spi)
pm_runtime_set_autosuspend_delay(trf->dev, autosuspend_delay);
pm_runtime_use_autosuspend(trf->dev);
- pm_runtime_enable(trf->dev);
+
+ ret = trf7970a_startup(trf);
+ if (ret)
+ goto err_free_ddev;
ret = nfc_digital_register_device(trf->ddev);
if (ret) {
dev_err(trf->dev, "Can't register NFC digital device: %d\n",
ret);
- goto err_free_ddev;
+ goto err_shutdown;
}
return 0;
+err_shutdown:
+ trf7970a_shutdown(trf);
err_free_ddev:
- pm_runtime_disable(trf->dev);
nfc_digital_free_device(trf->ddev);
err_disable_regulator:
regulator_disable(trf->regulator);
@@ -1376,25 +2105,10 @@ static int trf7970a_remove(struct spi_device *spi)
mutex_lock(&trf->lock);
- switch (trf->state) {
- case TRF7970A_ST_WAIT_FOR_TX_FIFO:
- case TRF7970A_ST_WAIT_FOR_RX_DATA:
- case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
- case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
- trf7970a_send_err_upstream(trf, -ECANCELED);
- /* FALLTHROUGH */
- case TRF7970A_ST_IDLE:
- case TRF7970A_ST_IDLE_RX_BLOCKED:
- pm_runtime_put_sync(trf->dev);
- break;
- default:
- break;
- }
+ trf7970a_shutdown(trf);
mutex_unlock(&trf->lock);
- pm_runtime_disable(trf->dev);
-
nfc_digital_unregister_device(trf->ddev);
nfc_digital_free_device(trf->ddev);
@@ -1405,72 +2119,83 @@ static int trf7970a_remove(struct spi_device *spi)
return 0;
}
-#ifdef CONFIG_PM_RUNTIME
-static int trf7970a_pm_runtime_suspend(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int trf7970a_suspend(struct device *dev)
+{
+ struct spi_device *spi = container_of(dev, struct spi_device, dev);
+ struct trf7970a *trf = spi_get_drvdata(spi);
+
+ dev_dbg(dev, "Suspend\n");
+
+ mutex_lock(&trf->lock);
+
+ trf7970a_shutdown(trf);
+
+ mutex_unlock(&trf->lock);
+
+ return 0;
+}
+
+static int trf7970a_resume(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
struct trf7970a *trf = spi_get_drvdata(spi);
int ret;
- dev_dbg(dev, "Runtime suspend\n");
+ dev_dbg(dev, "Resume\n");
- if (trf->state != TRF7970A_ST_OFF) {
- dev_dbg(dev, "Can't suspend - not in OFF state (%d)\n",
- trf->state);
- return -EBUSY;
- }
+ mutex_lock(&trf->lock);
- gpio_set_value(trf->en_gpio, 0);
- gpio_set_value(trf->en2_gpio, 0);
+ ret = trf7970a_startup(trf);
- ret = regulator_disable(trf->regulator);
- if (ret)
- dev_err(dev, "%s - Can't disable VIN: %d\n", __func__, ret);
+ mutex_unlock(&trf->lock);
return ret;
}
+#endif
-static int trf7970a_pm_runtime_resume(struct device *dev)
+#ifdef CONFIG_PM_RUNTIME
+static int trf7970a_pm_runtime_suspend(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
struct trf7970a *trf = spi_get_drvdata(spi);
int ret;
- dev_dbg(dev, "Runtime resume\n");
+ dev_dbg(dev, "Runtime suspend\n");
- ret = regulator_enable(trf->regulator);
- if (ret) {
- dev_err(dev, "%s - Can't enable VIN: %d\n", __func__, ret);
- return ret;
- }
+ mutex_lock(&trf->lock);
- usleep_range(5000, 6000);
+ ret = trf7970a_power_down(trf);
- gpio_set_value(trf->en2_gpio, 1);
- usleep_range(1000, 2000);
- gpio_set_value(trf->en_gpio, 1);
+ mutex_unlock(&trf->lock);
- usleep_range(20000, 21000);
+ return ret;
+}
- ret = trf7970a_init(trf);
- if (ret) {
- dev_err(dev, "%s - Can't initialize: %d\n", __func__, ret);
- return ret;
- }
+static int trf7970a_pm_runtime_resume(struct device *dev)
+{
+ struct spi_device *spi = container_of(dev, struct spi_device, dev);
+ struct trf7970a *trf = spi_get_drvdata(spi);
+ int ret;
- pm_runtime_mark_last_busy(dev);
+ dev_dbg(dev, "Runtime resume\n");
- return 0;
+ ret = trf7970a_power_up(trf);
+ if (!ret)
+ pm_runtime_mark_last_busy(dev);
+
+ return ret;
}
#endif
static const struct dev_pm_ops trf7970a_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(trf7970a_suspend, trf7970a_resume)
SET_RUNTIME_PM_OPS(trf7970a_pm_runtime_suspend,
trf7970a_pm_runtime_resume, NULL)
};
static const struct spi_device_id trf7970a_id_table[] = {
- { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA },
+ { "trf7970a", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, trf7970a_id_table);
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index fbfa4e4..9eca9ae 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -2,6 +2,7 @@
* The NFC Controller Interface is the communication protocol between an
* NFC Controller (NFCC) and a Device Host (DH).
*
+ * Copyright (C) 2014 Marvell International Ltd.
* Copyright (C) 2011 Texas Instruments, Inc.
*
* Written by Ilan Elias <ilane@ti.com>
@@ -65,19 +66,18 @@
#define NCI_NFC_F_PASSIVE_POLL_MODE 0x02
#define NCI_NFC_A_ACTIVE_POLL_MODE 0x03
#define NCI_NFC_F_ACTIVE_POLL_MODE 0x05
-#define NCI_NFC_15693_PASSIVE_POLL_MODE 0x06
+#define NCI_NFC_V_PASSIVE_POLL_MODE 0x06
#define NCI_NFC_A_PASSIVE_LISTEN_MODE 0x80
#define NCI_NFC_B_PASSIVE_LISTEN_MODE 0x81
#define NCI_NFC_F_PASSIVE_LISTEN_MODE 0x82
#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
-#define NCI_NFC_15693_PASSIVE_LISTEN_MODE 0x86
/* NCI RF Technologies */
#define NCI_NFC_RF_TECHNOLOGY_A 0x00
#define NCI_NFC_RF_TECHNOLOGY_B 0x01
#define NCI_NFC_RF_TECHNOLOGY_F 0x02
-#define NCI_NFC_RF_TECHNOLOGY_15693 0x03
+#define NCI_NFC_RF_TECHNOLOGY_V 0x03
/* NCI Bit Rates */
#define NCI_NFC_BIT_RATE_106 0x00
@@ -87,6 +87,7 @@
#define NCI_NFC_BIT_RATE_1695 0x04
#define NCI_NFC_BIT_RATE_3390 0x05
#define NCI_NFC_BIT_RATE_6780 0x06
+#define NCI_NFC_BIT_RATE_26 0x20
/* NCI RF Protocols */
#define NCI_RF_PROTOCOL_UNKNOWN 0x00
@@ -95,6 +96,7 @@
#define NCI_RF_PROTOCOL_T3T 0x03
#define NCI_RF_PROTOCOL_ISO_DEP 0x04
#define NCI_RF_PROTOCOL_NFC_DEP 0x05
+#define NCI_RF_PROTOCOL_T5T 0x06
/* NCI RF Interfaces */
#define NCI_RF_INTERFACE_NFCEE_DIRECT 0x00
@@ -328,6 +330,12 @@ struct rf_tech_specific_params_nfcf_poll {
__u8 sensf_res[18]; /* 16 or 18 Bytes */
} __packed;
+struct rf_tech_specific_params_nfcv_poll {
+ __u8 res_flags;
+ __u8 dsfid;
+ __u8 uid[8]; /* 8 Bytes */
+} __packed;
+
struct nci_rf_discover_ntf {
__u8 rf_discovery_id;
__u8 rf_protocol;
@@ -338,6 +346,7 @@ struct nci_rf_discover_ntf {
struct rf_tech_specific_params_nfca_poll nfca_poll;
struct rf_tech_specific_params_nfcb_poll nfcb_poll;
struct rf_tech_specific_params_nfcf_poll nfcf_poll;
+ struct rf_tech_specific_params_nfcv_poll nfcv_poll;
} rf_tech_specific_params;
__u8 ntf_type;
@@ -372,6 +381,7 @@ struct nci_rf_intf_activated_ntf {
struct rf_tech_specific_params_nfca_poll nfca_poll;
struct rf_tech_specific_params_nfcb_poll nfcb_poll;
struct rf_tech_specific_params_nfcf_poll nfcf_poll;
+ struct rf_tech_specific_params_nfcv_poll nfcv_poll;
} rf_tech_specific_params;
__u8 data_exch_rf_tech_and_mode;
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 1f9a0f5..75d10e6 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -64,10 +64,11 @@ enum nci_state {
struct nci_dev;
struct nci_ops {
- int (*open)(struct nci_dev *ndev);
- int (*close)(struct nci_dev *ndev);
- int (*send)(struct nci_dev *ndev, struct sk_buff *skb);
- int (*setup)(struct nci_dev *ndev);
+ int (*open)(struct nci_dev *ndev);
+ int (*close)(struct nci_dev *ndev);
+ int (*send)(struct nci_dev *ndev, struct sk_buff *skb);
+ int (*setup)(struct nci_dev *ndev);
+ __u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
};
#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index e1638da..b60aa35 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -33,6 +33,8 @@
#define DIGITAL_ATR_REQ_MAX_SIZE 64
#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
+ (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
#define DIGITAL_GB_BIT 0x02
#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
@@ -127,6 +129,98 @@ static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
return 0;
}
+static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
+ struct sk_buff *resp)
+{
+ struct nfc_target *target = arg;
+ struct digital_psl_res *psl_res;
+ int rc;
+
+ if (IS_ERR(resp)) {
+ rc = PTR_ERR(resp);
+ resp = NULL;
+ goto exit;
+ }
+
+ rc = ddev->skb_check_crc(resp);
+ if (rc) {
+ PROTOCOL_ERR("14.4.1.6");
+ goto exit;
+ }
+
+ rc = digital_skb_pull_dep_sod(ddev, resp);
+ if (rc) {
+ PROTOCOL_ERR("14.4.1.2");
+ goto exit;
+ }
+
+ psl_res = (struct digital_psl_res *)resp->data;
+
+ if ((resp->len != sizeof(*psl_res)) ||
+ (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
+ (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
+ rc = -EIO;
+ goto exit;
+ }
+
+ rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
+ NFC_DIGITAL_RF_TECH_424F);
+ if (rc)
+ goto exit;
+
+ rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
+ NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
+ if (rc)
+ goto exit;
+
+ if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
+ (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
+ ddev->skb_add_crc = digital_skb_add_crc_f;
+ ddev->skb_check_crc = digital_skb_check_crc_f;
+ }
+
+ ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
+
+ nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
+ NFC_RF_INITIATOR);
+
+ ddev->curr_nfc_dep_pni = 0;
+
+exit:
+ dev_kfree_skb(resp);
+
+ if (rc)
+ ddev->curr_protocol = 0;
+}
+
+static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
+ struct nfc_target *target)
+{
+ struct sk_buff *skb;
+ struct digital_psl_req *psl_req;
+
+ skb = digital_skb_alloc(ddev, sizeof(*psl_req));
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, sizeof(*psl_req));
+
+ psl_req = (struct digital_psl_req *)skb->data;
+
+ psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
+ psl_req->cmd = DIGITAL_CMD_PSL_REQ;
+ psl_req->did = 0;
+ psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
+ psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
+
+ digital_skb_push_dep_sod(ddev, skb);
+
+ ddev->skb_add_crc(skb);
+
+ return digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
+ target);
+}
+
static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp)
{
@@ -166,6 +260,13 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
if (rc)
goto exit;
+ if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
+ (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
+ rc = digital_in_send_psl_req(ddev, target);
+ if (!rc)
+ goto exit;
+ }
+
rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
NFC_RF_INITIATOR);
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 2b400e1..90b16cb 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -231,6 +231,14 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
cmd.num_disc_configs++;
}
+ if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
+ (protocols & NFC_PROTO_ISO15693_MASK)) {
+ cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
+ NCI_NFC_V_PASSIVE_POLL_MODE;
+ cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
+ cmd.num_disc_configs++;
+ }
+
nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
(1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
&cmd);
@@ -751,10 +759,6 @@ int nci_register_device(struct nci_dev *ndev)
struct device *dev = &ndev->nfc_dev->dev;
char name[32];
- rc = nfc_register_device(ndev->nfc_dev);
- if (rc)
- goto exit;
-
ndev->flags = 0;
INIT_WORK(&ndev->cmd_work, nci_cmd_work);
@@ -762,7 +766,7 @@ int nci_register_device(struct nci_dev *ndev)
ndev->cmd_wq = create_singlethread_workqueue(name);
if (!ndev->cmd_wq) {
rc = -ENOMEM;
- goto unreg_exit;
+ goto exit;
}
INIT_WORK(&ndev->rx_work, nci_rx_work);
@@ -792,6 +796,10 @@ int nci_register_device(struct nci_dev *ndev)
mutex_init(&ndev->req_lock);
+ rc = nfc_register_device(ndev->nfc_dev);
+ if (rc)
+ goto destroy_rx_wq_exit;
+
goto exit;
destroy_rx_wq_exit:
@@ -800,9 +808,6 @@ destroy_rx_wq_exit:
destroy_cmd_wq_exit:
destroy_workqueue(ndev->cmd_wq);
-unreg_exit:
- nfc_unregister_device(ndev->nfc_dev);
-
exit:
return rc;
}
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index 6c3aef8..427ef2c 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -241,9 +241,12 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
/* strip the nci data header */
skb_pull(skb, NCI_DATA_HDR_SIZE);
- if (ndev->target_active_prot == NFC_PROTO_MIFARE) {
+ if (ndev->target_active_prot == NFC_PROTO_MIFARE ||
+ ndev->target_active_prot == NFC_PROTO_JEWEL ||
+ ndev->target_active_prot == NFC_PROTO_FELICA ||
+ ndev->target_active_prot == NFC_PROTO_ISO15693) {
/* frame I/F => remove the status byte */
- pr_debug("NFC_PROTO_MIFARE => remove the status byte\n");
+ pr_debug("frame I/F => remove the status byte\n");
skb_trim(skb, (skb->len - 1));
}
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index df91bb9..205b35f6 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -2,6 +2,7 @@
* The NFC Controller Interface is the communication protocol between an
* NFC Controller (NFCC) and a Device Host (DH).
*
+ * Copyright (C) 2014 Marvell International Ltd.
* Copyright (C) 2011 Texas Instruments, Inc.
*
* Written by Ilan Elias <ilane@ti.com>
@@ -155,6 +156,24 @@ static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
return data;
}
+static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev,
+ struct rf_tech_specific_params_nfcv_poll *nfcv_poll,
+ __u8 *data)
+{
+ ++data;
+ nfcv_poll->dsfid = *data++;
+ memcpy(nfcv_poll->uid, data, NFC_ISO15693_UID_MAXSIZE);
+ data += NFC_ISO15693_UID_MAXSIZE;
+ return data;
+}
+
+__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
+{
+ if (ndev->ops->get_rfprotocol)
+ return ndev->ops->get_rfprotocol(ndev, rf_protocol);
+ return 0;
+}
+
static int nci_add_new_protocol(struct nci_dev *ndev,
struct nfc_target *target,
__u8 rf_protocol,
@@ -164,6 +183,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
struct rf_tech_specific_params_nfca_poll *nfca_poll;
struct rf_tech_specific_params_nfcb_poll *nfcb_poll;
struct rf_tech_specific_params_nfcf_poll *nfcf_poll;
+ struct rf_tech_specific_params_nfcv_poll *nfcv_poll;
__u32 protocol;
if (rf_protocol == NCI_RF_PROTOCOL_T1T)
@@ -179,8 +199,10 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
protocol = NFC_PROTO_FELICA_MASK;
else if (rf_protocol == NCI_RF_PROTOCOL_NFC_DEP)
protocol = NFC_PROTO_NFC_DEP_MASK;
+ else if (rf_protocol == NCI_RF_PROTOCOL_T5T)
+ protocol = NFC_PROTO_ISO15693_MASK;
else
- protocol = 0;
+ protocol = nci_get_prop_rf_protocol(ndev, rf_protocol);
if (!(protocol & ndev->poll_prots)) {
pr_err("the target found does not have the desired protocol\n");
@@ -213,6 +235,12 @@ static int nci_add_new_protocol(struct nci_dev *ndev,
memcpy(target->sensf_res, nfcf_poll->sensf_res,
target->sensf_res_len);
}
+ } else if (rf_tech_and_mode == NCI_NFC_V_PASSIVE_POLL_MODE) {
+ nfcv_poll = (struct rf_tech_specific_params_nfcv_poll *)params;
+
+ target->is_iso15693 = 1;
+ target->iso15693_dsfid = nfcv_poll->dsfid;
+ memcpy(target->iso15693_uid, nfcv_poll->uid, NFC_ISO15693_UID_MAXSIZE);
} else {
pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode);
return -EPROTO;
@@ -305,6 +333,11 @@ static void nci_rf_discover_ntf_packet(struct nci_dev *ndev,
&(ntf.rf_tech_specific_params.nfcf_poll), data);
break;
+ case NCI_NFC_V_PASSIVE_POLL_MODE:
+ data = nci_extract_rf_params_nfcv_passive_poll(ndev,
+ &(ntf.rf_tech_specific_params.nfcv_poll), data);
+ break;
+
default:
pr_err("unsupported rf_tech_and_mode 0x%x\n",
ntf.rf_tech_and_mode);
@@ -455,6 +488,11 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
&(ntf.rf_tech_specific_params.nfcf_poll), data);
break;
+ case NCI_NFC_V_PASSIVE_POLL_MODE:
+ data = nci_extract_rf_params_nfcv_passive_poll(ndev,
+ &(ntf.rf_tech_specific_params.nfcv_poll), data);
+ break;
+
default:
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
ntf.activation_rf_tech_and_mode);
OpenPOWER on IntegriCloud