diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-09-26 19:37:02 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-09-26 19:37:02 +0200 |
commit | 330bd4ec9d046a6e6f8b7cf4a53c2d15b7705e00 (patch) | |
tree | d278d8325e1e1cfca1ecfaf592158dcec10539f2 | |
parent | Merge branch 'for-linville' of git://github.com/kvalo/ath (diff) | |
parent | NFC: st21nfca: Fix potential double kfree_skb error (diff) | |
download | linux-330bd4ec9d046a6e6f8b7cf4a53c2d15b7705e00.tar.xz linux-330bd4ec9d046a6e6f8b7cf4a53c2d15b7705e00.zip |
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.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/net/nfc/trf7970a.txt | 8 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/i2c.c | 34 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.c | 59 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.h | 21 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca_dep.c | 59 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/i2c.c | 67 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/ndlc.c | 6 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/ndlc.h | 4 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/st21nfcb.c | 27 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/st21nfcb.h | 2 | ||||
-rw-r--r-- | drivers/nfc/trf7970a.c | 1059 | ||||
-rw-r--r-- | include/net/nfc/nci.h | 16 | ||||
-rw-r--r-- | include/net/nfc/nci_core.h | 9 | ||||
-rw-r--r-- | net/nfc/digital_dep.c | 101 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 21 | ||||
-rw-r--r-- | net/nfc/nci/data.c | 7 | ||||
-rw-r--r-- | net/nfc/nci/ntf.c | 40 |
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 3b58ae480344..9005608cbbd1 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 1e436133685f..7c89ca290ced 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 ff31939978ae..0ea756b77519 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 a902b0551c86..a89e56c2c749 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 96fe5a62dc0d..a0b77f1ba6d9 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 b2d9957b57f8..bfb6df56c505 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 8af880ead5db..c5d2427a3db2 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 83c97c36112b..e7bff8921d11 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 c30a2f0faa5f..b28140e0cd78 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 4d95863e3063..ea63d5877831 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 4bbbebb9f34d..ea58a56ad794 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 3b78b031e617..d2ccd2890647 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 fbfa4e471abb..9eca9ae2280c 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 1f9a0f5272fe..75d10e625c49 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 e1638dab076d..b60aa35c074f 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 2b400e1a8695..90b16cb40058 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 6c3aef852876..427ef2c7ab68 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 df91bb95b12a..205b35f666db 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); |