These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / nfc / trf7970a.c
index aa6a333..f857feb 100644 (file)
  */
 #define TRF7970A_QUIRK_IRQ_STATUS_READ         BIT(0)
 #define TRF7970A_QUIRK_EN2_MUST_STAY_LOW       BIT(1)
+#define TRF7970A_QUIRK_T5T_RMB_EXTRA_BYTE      BIT(2)
 
 /* Direct commands */
 #define TRF7970A_CMD_IDLE                      0x00
 
 #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_SDD_EN       BIT(5)
 #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)
@@ -446,6 +447,7 @@ struct trf7970a {
        u8                              md_rf_tech;
        u8                              tx_cmd;
        bool                            issue_eof;
+       bool                            adjust_resp_len;
        int                             en2_gpio;
        int                             en_gpio;
        struct mutex                    lock;
@@ -626,6 +628,13 @@ static void trf7970a_send_upstream(struct trf7970a *trf)
                trf->aborting = false;
        }
 
+       if (trf->adjust_resp_len) {
+               if (trf->rx_skb)
+                       skb_trim(trf->rx_skb, trf->rx_skb->len - 1);
+
+               trf->adjust_resp_len = false;
+       }
+
        trf->cb(trf->ddev, trf->cb_arg, trf->rx_skb);
 
        trf->rx_skb = NULL;
@@ -1429,10 +1438,15 @@ static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
                        trf->iso_ctrl = iso_ctrl;
                }
 
-               if ((trf->framing == NFC_DIGITAL_FRAMING_ISO15693_T5T) &&
-                               trf7970a_is_iso15693_write_or_lock(req[1]) &&
-                               (req[0] & ISO15693_REQ_FLAG_OPTION))
-                       trf->issue_eof = true;
+               if (trf->framing == NFC_DIGITAL_FRAMING_ISO15693_T5T) {
+                       if (trf7970a_is_iso15693_write_or_lock(req[1]) &&
+                                       (req[0] & ISO15693_REQ_FLAG_OPTION))
+                               trf->issue_eof = true;
+                       else if ((trf->quirks &
+                                       TRF7970A_QUIRK_T5T_RMB_EXTRA_BYTE) &&
+                                (req[1] == ISO15693_CMD_READ_MULTIPLE_BLOCK))
+                               trf->adjust_resp_len = true;
+               }
        }
 
        return 0;
@@ -1992,6 +2006,9 @@ static int trf7970a_probe(struct spi_device *spi)
                return ret;
        }
 
+       if (of_property_read_bool(np, "t5t-rmb-extra-byte-quirk"))
+               trf->quirks |= TRF7970A_QUIRK_T5T_RMB_EXTRA_BYTE;
+
        if (of_property_read_bool(np, "irq-status-read-quirk"))
                trf->quirks |= TRF7970A_QUIRK_IRQ_STATUS_READ;
 
@@ -2194,6 +2211,12 @@ static const struct dev_pm_ops trf7970a_pm_ops = {
                        trf7970a_pm_runtime_resume, NULL)
 };
 
+static const struct of_device_id trf7970a_of_match[] = {
+       { .compatible = "ti,trf7970a", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, trf7970a_of_match);
+
 static const struct spi_device_id trf7970a_id_table[] = {
        { "trf7970a", 0 },
        { }
@@ -2206,7 +2229,7 @@ static struct spi_driver trf7970a_spi_driver = {
        .id_table       = trf7970a_id_table,
        .driver         = {
                .name   = "trf7970a",
-               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(trf7970a_of_match),
                .pm     = &trf7970a_pm_ops,
        },
 };