mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-30 05:25:20 +08:00
NFC: trf7970a: Add ISO/IEC 15693 and Type 5 tag Support
Add support for ISO/IEC 15693 RF technology and Type 5 tags. Note that Type 5 tags used to be referred to as Type V tags. CC: Erick Macias <emacias@ti.com> CC: Felipe Balbi <balbi@ti.com> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
8006289108
commit
9d9304b321
@ -85,10 +85,26 @@
|
|||||||
* Unfortunately, that means that the driver has to peek into tx frames
|
* Unfortunately, that means that the driver has to peek into tx frames
|
||||||
* when the framing is 'NFC_DIGITAL_FRAMING_NFCA_T2T'. This is done by
|
* when the framing is 'NFC_DIGITAL_FRAMING_NFCA_T2T'. This is done by
|
||||||
* the trf7970a_per_cmd_config() routine.
|
* the trf7970a_per_cmd_config() routine.
|
||||||
|
*
|
||||||
|
* ISO/IEC 15693 frames specify whether to use single or double sub-carrier
|
||||||
|
* frequencies and whether to use low or high data rates in the flags byte
|
||||||
|
* of the frame. This means that the driver has to peek at all 15693 frames
|
||||||
|
* to determine what speed to set the communication to. In addition, write
|
||||||
|
* and lock commands use the OPTION flag to indicate that an EOF must be
|
||||||
|
* sent to the tag before it will send its response. So the driver has to
|
||||||
|
* examine all frames for that reason too.
|
||||||
|
*
|
||||||
|
* It is unclear how long to wait before sending the EOF. According to the
|
||||||
|
* 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
|
||||||
|
* reliably.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TRF7970A_SUPPORTED_PROTOCOLS \
|
#define TRF7970A_SUPPORTED_PROTOCOLS \
|
||||||
(NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK)
|
(NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \
|
||||||
|
NFC_PROTO_ISO15693_MASK)
|
||||||
|
|
||||||
/* TX data must be prefixed with a FIFO reset cmd, a cmd that depends
|
/* 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
|
* on what the current framing is, the address of the TX length byte 1
|
||||||
@ -106,6 +122,7 @@
|
|||||||
|
|
||||||
#define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 5
|
#define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 5
|
||||||
#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3
|
#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3
|
||||||
|
#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20
|
||||||
|
|
||||||
/* Quirks */
|
/* Quirks */
|
||||||
/* Erratum: When reading IRQ Status register on trf7970a, we must issue a
|
/* Erratum: When reading IRQ Status register on trf7970a, we must issue a
|
||||||
@ -265,6 +282,36 @@
|
|||||||
/* NFC (ISO/IEC 14443A) Type 2 Tag commands */
|
/* NFC (ISO/IEC 14443A) Type 2 Tag commands */
|
||||||
#define NFC_T2T_CMD_READ 0x30
|
#define NFC_T2T_CMD_READ 0x30
|
||||||
|
|
||||||
|
/* ISO 15693 commands codes */
|
||||||
|
#define ISO15693_CMD_INVENTORY 0x01
|
||||||
|
#define ISO15693_CMD_READ_SINGLE_BLOCK 0x20
|
||||||
|
#define ISO15693_CMD_WRITE_SINGLE_BLOCK 0x21
|
||||||
|
#define ISO15693_CMD_LOCK_BLOCK 0x22
|
||||||
|
#define ISO15693_CMD_READ_MULTIPLE_BLOCK 0x23
|
||||||
|
#define ISO15693_CMD_WRITE_MULTIPLE_BLOCK 0x24
|
||||||
|
#define ISO15693_CMD_SELECT 0x25
|
||||||
|
#define ISO15693_CMD_RESET_TO_READY 0x26
|
||||||
|
#define ISO15693_CMD_WRITE_AFI 0x27
|
||||||
|
#define ISO15693_CMD_LOCK_AFI 0x28
|
||||||
|
#define ISO15693_CMD_WRITE_DSFID 0x29
|
||||||
|
#define ISO15693_CMD_LOCK_DSFID 0x2a
|
||||||
|
#define ISO15693_CMD_GET_SYSTEM_INFO 0x2b
|
||||||
|
#define ISO15693_CMD_GET_MULTIPLE_BLOCK_SECURITY_STATUS 0x2c
|
||||||
|
|
||||||
|
/* ISO 15693 request and response flags */
|
||||||
|
#define ISO15693_REQ_FLAG_SUB_CARRIER BIT(0)
|
||||||
|
#define ISO15693_REQ_FLAG_DATA_RATE BIT(1)
|
||||||
|
#define ISO15693_REQ_FLAG_INVENTORY BIT(2)
|
||||||
|
#define ISO15693_REQ_FLAG_PROTOCOL_EXT BIT(3)
|
||||||
|
#define ISO15693_REQ_FLAG_SELECT BIT(4)
|
||||||
|
#define ISO15693_REQ_FLAG_AFI BIT(4)
|
||||||
|
#define ISO15693_REQ_FLAG_ADDRESS BIT(5)
|
||||||
|
#define ISO15693_REQ_FLAG_NB_SLOTS BIT(5)
|
||||||
|
#define ISO15693_REQ_FLAG_OPTION BIT(6)
|
||||||
|
|
||||||
|
#define ISO15693_REQ_FLAG_SPEED_MASK \
|
||||||
|
(ISO15693_REQ_FLAG_SUB_CARRIER | ISO15693_REQ_FLAG_DATA_RATE)
|
||||||
|
|
||||||
enum trf7970a_state {
|
enum trf7970a_state {
|
||||||
TRF7970A_ST_OFF,
|
TRF7970A_ST_OFF,
|
||||||
TRF7970A_ST_IDLE,
|
TRF7970A_ST_IDLE,
|
||||||
@ -272,6 +319,7 @@ enum trf7970a_state {
|
|||||||
TRF7970A_ST_WAIT_FOR_TX_FIFO,
|
TRF7970A_ST_WAIT_FOR_TX_FIFO,
|
||||||
TRF7970A_ST_WAIT_FOR_RX_DATA,
|
TRF7970A_ST_WAIT_FOR_RX_DATA,
|
||||||
TRF7970A_ST_WAIT_FOR_RX_DATA_CONT,
|
TRF7970A_ST_WAIT_FOR_RX_DATA_CONT,
|
||||||
|
TRF7970A_ST_WAIT_TO_ISSUE_EOF,
|
||||||
TRF7970A_ST_MAX
|
TRF7970A_ST_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -293,6 +341,7 @@ struct trf7970a {
|
|||||||
int technology;
|
int technology;
|
||||||
int framing;
|
int framing;
|
||||||
u8 tx_cmd;
|
u8 tx_cmd;
|
||||||
|
bool issue_eof;
|
||||||
int en2_gpio;
|
int en2_gpio;
|
||||||
int en_gpio;
|
int en_gpio;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
@ -453,10 +502,15 @@ static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb,
|
|||||||
if (skb->len > 0) {
|
if (skb->len > 0) {
|
||||||
trf->state = TRF7970A_ST_WAIT_FOR_TX_FIFO;
|
trf->state = TRF7970A_ST_WAIT_FOR_TX_FIFO;
|
||||||
timeout = TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT;
|
timeout = TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT;
|
||||||
|
} else {
|
||||||
|
if (trf->issue_eof) {
|
||||||
|
trf->state = TRF7970A_ST_WAIT_TO_ISSUE_EOF;
|
||||||
|
timeout = TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF;
|
||||||
} else {
|
} else {
|
||||||
trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA;
|
trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA;
|
||||||
timeout = trf->timeout;
|
timeout = trf->timeout;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n", timeout,
|
dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n", timeout,
|
||||||
trf->state);
|
trf->state);
|
||||||
@ -631,6 +685,10 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
|
|||||||
trf7970a_send_err_upstream(trf, -EIO);
|
trf7970a_send_err_upstream(trf, -EIO);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
|
||||||
|
if (status != TRF7970A_IRQ_STATUS_TX)
|
||||||
|
trf7970a_send_err_upstream(trf, -EIO);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(trf->dev, "%s - Driver in invalid state: %d\n",
|
dev_err(trf->dev, "%s - Driver in invalid state: %d\n",
|
||||||
__func__, trf->state);
|
__func__, trf->state);
|
||||||
@ -640,6 +698,29 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void trf7970a_issue_eof(struct trf7970a *trf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_dbg(trf->dev, "Issuing EOF\n");
|
||||||
|
|
||||||
|
ret = trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);
|
||||||
|
if (ret)
|
||||||
|
trf7970a_send_err_upstream(trf, ret);
|
||||||
|
|
||||||
|
ret = trf7970a_cmd(trf, TRF7970A_CMD_EOF);
|
||||||
|
if (ret)
|
||||||
|
trf7970a_send_err_upstream(trf, ret);
|
||||||
|
|
||||||
|
trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA;
|
||||||
|
|
||||||
|
dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n",
|
||||||
|
trf->timeout, trf->state);
|
||||||
|
|
||||||
|
schedule_delayed_work(&trf->timeout_work,
|
||||||
|
msecs_to_jiffies(trf->timeout));
|
||||||
|
}
|
||||||
|
|
||||||
static void trf7970a_timeout_work_handler(struct work_struct *work)
|
static void trf7970a_timeout_work_handler(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct trf7970a *trf = container_of(work, struct trf7970a,
|
struct trf7970a *trf = container_of(work, struct trf7970a,
|
||||||
@ -654,6 +735,8 @@ static void trf7970a_timeout_work_handler(struct work_struct *work)
|
|||||||
trf->ignore_timeout = false;
|
trf->ignore_timeout = false;
|
||||||
else if (trf->state == TRF7970A_ST_WAIT_FOR_RX_DATA_CONT)
|
else if (trf->state == TRF7970A_ST_WAIT_FOR_RX_DATA_CONT)
|
||||||
trf7970a_send_upstream(trf); /* No more rx data so send up */
|
trf7970a_send_upstream(trf); /* No more rx data so send up */
|
||||||
|
else if (trf->state == TRF7970A_ST_WAIT_TO_ISSUE_EOF)
|
||||||
|
trf7970a_issue_eof(trf);
|
||||||
else
|
else
|
||||||
trf7970a_send_err_upstream(trf, -ETIMEDOUT);
|
trf7970a_send_err_upstream(trf, -ETIMEDOUT);
|
||||||
|
|
||||||
@ -801,6 +884,9 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech)
|
|||||||
case NFC_DIGITAL_RF_TECH_106A:
|
case NFC_DIGITAL_RF_TECH_106A:
|
||||||
trf->iso_ctrl = TRF7970A_ISO_CTRL_14443A_106;
|
trf->iso_ctrl = TRF7970A_ISO_CTRL_14443A_106;
|
||||||
break;
|
break;
|
||||||
|
case NFC_DIGITAL_RF_TECH_ISO15693:
|
||||||
|
trf->iso_ctrl = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);
|
dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -823,6 +909,8 @@ static int trf7970a_config_framing(struct trf7970a *trf, int framing)
|
|||||||
break;
|
break;
|
||||||
case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
|
case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
|
||||||
case NFC_DIGITAL_FRAMING_NFCA_T4T:
|
case NFC_DIGITAL_FRAMING_NFCA_T4T:
|
||||||
|
case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
|
||||||
|
case NFC_DIGITAL_FRAMING_ISO15693_T5T:
|
||||||
trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
|
trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
|
||||||
trf->iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
|
trf->iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
|
||||||
break;
|
break;
|
||||||
@ -873,15 +961,39 @@ err_out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int trf7970a_is_iso15693_write_or_lock(u8 cmd)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case ISO15693_CMD_WRITE_SINGLE_BLOCK:
|
||||||
|
case ISO15693_CMD_LOCK_BLOCK:
|
||||||
|
case ISO15693_CMD_WRITE_MULTIPLE_BLOCK:
|
||||||
|
case ISO15693_CMD_WRITE_AFI:
|
||||||
|
case ISO15693_CMD_LOCK_AFI:
|
||||||
|
case ISO15693_CMD_WRITE_DSFID:
|
||||||
|
case ISO15693_CMD_LOCK_DSFID:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
|
static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
u8 *req = skb->data;
|
u8 *req = skb->data;
|
||||||
u8 special_fcn_reg1;
|
u8 special_fcn_reg1, iso_ctrl;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
trf->issue_eof = false;
|
||||||
|
|
||||||
/* When issuing Type 2 read command, make sure the '4_bit_RX' bit in
|
/* When issuing Type 2 read command, make sure the '4_bit_RX' bit in
|
||||||
* special functions register 1 is cleared; otherwise, its a write or
|
* special functions register 1 is cleared; otherwise, its a write or
|
||||||
* sector select command and '4_bit_RX' must be set.
|
* sector select command and '4_bit_RX' must be set.
|
||||||
|
*
|
||||||
|
* When issuing an ISO 15693 command, inspect the flags byte to see
|
||||||
|
* what speed to use. Also, remember if the OPTION flag is set on
|
||||||
|
* a Type 5 write or lock command so the driver will know that it
|
||||||
|
* has to send an EOF in order to get a response.
|
||||||
*/
|
*/
|
||||||
if ((trf->technology == NFC_DIGITAL_RF_TECH_106A) &&
|
if ((trf->technology == NFC_DIGITAL_RF_TECH_106A) &&
|
||||||
(trf->framing == NFC_DIGITAL_FRAMING_NFCA_T2T)) {
|
(trf->framing == NFC_DIGITAL_FRAMING_NFCA_T2T)) {
|
||||||
@ -898,6 +1010,37 @@ static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
|
|||||||
|
|
||||||
trf->special_fcn_reg1 = special_fcn_reg1;
|
trf->special_fcn_reg1 = special_fcn_reg1;
|
||||||
}
|
}
|
||||||
|
} else if (trf->technology == NFC_DIGITAL_RF_TECH_ISO15693) {
|
||||||
|
iso_ctrl = trf->iso_ctrl & ~TRF7970A_ISO_CTRL_RFID_SPEED_MASK;
|
||||||
|
|
||||||
|
switch (req[0] & ISO15693_REQ_FLAG_SPEED_MASK) {
|
||||||
|
case 0x00:
|
||||||
|
iso_ctrl |= TRF7970A_ISO_CTRL_15693_SGL_1OF4_662;
|
||||||
|
break;
|
||||||
|
case ISO15693_REQ_FLAG_SUB_CARRIER:
|
||||||
|
iso_ctrl |= TRF7970A_ISO_CTRL_15693_DBL_1OF4_667a;
|
||||||
|
break;
|
||||||
|
case ISO15693_REQ_FLAG_DATA_RATE:
|
||||||
|
iso_ctrl |= TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648;
|
||||||
|
break;
|
||||||
|
case (ISO15693_REQ_FLAG_SUB_CARRIER |
|
||||||
|
ISO15693_REQ_FLAG_DATA_RATE):
|
||||||
|
iso_ctrl |= TRF7970A_ISO_CTRL_15693_DBL_1OF4_2669;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iso_ctrl != trf->iso_ctrl) {
|
||||||
|
ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1185,6 +1328,7 @@ static int trf7970a_remove(struct spi_device *spi)
|
|||||||
case TRF7970A_ST_WAIT_FOR_TX_FIFO:
|
case TRF7970A_ST_WAIT_FOR_TX_FIFO:
|
||||||
case TRF7970A_ST_WAIT_FOR_RX_DATA:
|
case TRF7970A_ST_WAIT_FOR_RX_DATA:
|
||||||
case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
|
case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
|
||||||
|
case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
|
||||||
trf7970a_send_err_upstream(trf, -ECANCELED);
|
trf7970a_send_err_upstream(trf, -ECANCELED);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user