18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TI TRF7970a RFID/NFC Transceiver Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Erick Macias <emacias@ti.com> 88c2ecf20Sopenharmony_ci * Author: Felipe Balbi <balbi@ti.com> 98c2ecf20Sopenharmony_ci * Author: Mark A. Greer <mgreer@animalcreek.com> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/device.h> 148c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 178c2ecf20Sopenharmony_ci#include <linux/nfc.h> 188c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 198c2ecf20Sopenharmony_ci#include <linux/delay.h> 208c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 218c2ecf20Sopenharmony_ci#include <linux/of.h> 228c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 238c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <net/nfc/nfc.h> 268c2ecf20Sopenharmony_ci#include <net/nfc/digital.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* There are 3 ways the host can communicate with the trf7970a: 298c2ecf20Sopenharmony_ci * parallel mode, SPI with Slave Select (SS) mode, and SPI without 308c2ecf20Sopenharmony_ci * SS mode. The driver only supports the two SPI modes. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * The trf7970a is very timing sensitive and the VIN, EN2, and EN 338c2ecf20Sopenharmony_ci * pins must asserted in that order and with specific delays in between. 348c2ecf20Sopenharmony_ci * The delays used in the driver were provided by TI and have been 358c2ecf20Sopenharmony_ci * confirmed to work with this driver. There is a bug with the current 368c2ecf20Sopenharmony_ci * version of the trf7970a that requires that EN2 remain low no matter 378c2ecf20Sopenharmony_ci * what. If it goes high, it will generate an RF field even when in 388c2ecf20Sopenharmony_ci * passive target mode. TI has indicated that the chip will work okay 398c2ecf20Sopenharmony_ci * when EN2 is left low. The 'en2-rf-quirk' device tree property 408c2ecf20Sopenharmony_ci * indicates that trf7970a currently being used has the erratum and 418c2ecf20Sopenharmony_ci * that EN2 must be kept low. 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * Timeouts are implemented using the delayed workqueue kernel facility. 448c2ecf20Sopenharmony_ci * Timeouts are required so things don't hang when there is no response 458c2ecf20Sopenharmony_ci * from the trf7970a (or tag). Using this mechanism creates a race with 468c2ecf20Sopenharmony_ci * interrupts, however. That is, an interrupt and a timeout could occur 478c2ecf20Sopenharmony_ci * closely enough together that one is blocked by the mutex while the other 488c2ecf20Sopenharmony_ci * executes. When the timeout handler executes first and blocks the 498c2ecf20Sopenharmony_ci * interrupt handler, it will eventually set the state to IDLE so the 508c2ecf20Sopenharmony_ci * interrupt handler will check the state and exit with no harm done. 518c2ecf20Sopenharmony_ci * When the interrupt handler executes first and blocks the timeout handler, 528c2ecf20Sopenharmony_ci * the cancel_delayed_work() call will know that it didn't cancel the 538c2ecf20Sopenharmony_ci * work item (i.e., timeout) and will return zero. That return code is 548c2ecf20Sopenharmony_ci * used by the timer handler to indicate that it should ignore the timeout 558c2ecf20Sopenharmony_ci * once its unblocked. 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * Aborting an active command isn't as simple as it seems because the only 588c2ecf20Sopenharmony_ci * way to abort a command that's already been sent to the tag is so turn 598c2ecf20Sopenharmony_ci * off power to the tag. If we do that, though, we'd have to go through 608c2ecf20Sopenharmony_ci * the entire anticollision procedure again but the digital layer doesn't 618c2ecf20Sopenharmony_ci * support that. So, if an abort is received before trf7970a_send_cmd() 628c2ecf20Sopenharmony_ci * has sent the command to the tag, it simply returns -ECANCELED. If the 638c2ecf20Sopenharmony_ci * command has already been sent to the tag, then the driver continues 648c2ecf20Sopenharmony_ci * normally and recieves the response data (or error) but just before 658c2ecf20Sopenharmony_ci * sending the data upstream, it frees the rx_skb and sends -ECANCELED 668c2ecf20Sopenharmony_ci * upstream instead. If the command failed, that error will be sent 678c2ecf20Sopenharmony_ci * upstream. 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * When recieving data from a tag and the interrupt status register has 708c2ecf20Sopenharmony_ci * only the SRX bit set, it means that all of the data has been received 718c2ecf20Sopenharmony_ci * (once what's in the fifo has been read). However, depending on timing 728c2ecf20Sopenharmony_ci * an interrupt status with only the SRX bit set may not be recived. In 738c2ecf20Sopenharmony_ci * those cases, the timeout mechanism is used to wait 20 ms in case more 748c2ecf20Sopenharmony_ci * data arrives. After 20 ms, it is assumed that all of the data has been 758c2ecf20Sopenharmony_ci * received and the accumulated rx data is sent upstream. The 768c2ecf20Sopenharmony_ci * 'TRF7970A_ST_WAIT_FOR_RX_DATA_CONT' state is used for this purpose 778c2ecf20Sopenharmony_ci * (i.e., it indicates that some data has been received but we're not sure 788c2ecf20Sopenharmony_ci * if there is more coming so a timeout in this state means all data has 798c2ecf20Sopenharmony_ci * been received and there isn't an error). The delay is 20 ms since delays 808c2ecf20Sopenharmony_ci * of ~16 ms have been observed during testing. 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * When transmitting a frame larger than the FIFO size (127 bytes), the 838c2ecf20Sopenharmony_ci * driver will wait 20 ms for the FIFO to drain past the low-watermark 848c2ecf20Sopenharmony_ci * and generate an interrupt. The low-watermark set to 32 bytes so the 858c2ecf20Sopenharmony_ci * interrupt should fire after 127 - 32 = 95 bytes have been sent. At 868c2ecf20Sopenharmony_ci * the lowest possible bit rate (6.62 kbps for 15693), it will take up 878c2ecf20Sopenharmony_ci * to ~14.35 ms so 20 ms is used for the timeout. 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * Type 2 write and sector select commands respond with a 4-bit ACK or NACK. 908c2ecf20Sopenharmony_ci * Having only 4 bits in the FIFO won't normally generate an interrupt so 918c2ecf20Sopenharmony_ci * driver enables the '4_bit_RX' bit of the Special Functions register 1 928c2ecf20Sopenharmony_ci * to cause an interrupt in that case. Leaving that bit for a read command 938c2ecf20Sopenharmony_ci * messes up the data returned so it is only enabled when the framing is 948c2ecf20Sopenharmony_ci * 'NFC_DIGITAL_FRAMING_NFCA_T2T' and the command is not a read command. 958c2ecf20Sopenharmony_ci * Unfortunately, that means that the driver has to peek into tx frames 968c2ecf20Sopenharmony_ci * when the framing is 'NFC_DIGITAL_FRAMING_NFCA_T2T'. This is done by 978c2ecf20Sopenharmony_ci * the trf7970a_per_cmd_config() routine. 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * ISO/IEC 15693 frames specify whether to use single or double sub-carrier 1008c2ecf20Sopenharmony_ci * frequencies and whether to use low or high data rates in the flags byte 1018c2ecf20Sopenharmony_ci * of the frame. This means that the driver has to peek at all 15693 frames 1028c2ecf20Sopenharmony_ci * to determine what speed to set the communication to. In addition, write 1038c2ecf20Sopenharmony_ci * and lock commands use the OPTION flag to indicate that an EOF must be 1048c2ecf20Sopenharmony_ci * sent to the tag before it will send its response. So the driver has to 1058c2ecf20Sopenharmony_ci * examine all frames for that reason too. 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * It is unclear how long to wait before sending the EOF. According to the 1088c2ecf20Sopenharmony_ci * Note under Table 1-1 in section 1.6 of 1098c2ecf20Sopenharmony_ci * http://www.ti.com/lit/ug/scbu011/scbu011.pdf, that wait should be at least 1108c2ecf20Sopenharmony_ci * 10 ms for TI Tag-it HF-I tags; however testing has shown that is not long 1118c2ecf20Sopenharmony_ci * enough so 20 ms is used. So the timer is set to 40 ms - 20 ms to drain 1128c2ecf20Sopenharmony_ci * up to 127 bytes in the FIFO at the lowest bit rate plus another 20 ms to 1138c2ecf20Sopenharmony_ci * ensure the wait is long enough before sending the EOF. This seems to work 1148c2ecf20Sopenharmony_ci * reliably. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define TRF7970A_SUPPORTED_PROTOCOLS \ 1188c2ecf20Sopenharmony_ci (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ 1198c2ecf20Sopenharmony_ci NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_FELICA_MASK | \ 1208c2ecf20Sopenharmony_ci NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK) 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */ 1238c2ecf20Sopenharmony_ci#define TRF7970A_13MHZ_CLOCK_FREQUENCY 13560000 1248c2ecf20Sopenharmony_ci#define TRF7970A_27MHZ_CLOCK_FREQUENCY 27120000 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#define TRF7970A_RX_SKB_ALLOC_SIZE 256 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define TRF7970A_FIFO_SIZE 127 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* TX length is 3 nibbles long ==> 4KB - 1 bytes max */ 1318c2ecf20Sopenharmony_ci#define TRF7970A_TX_MAX (4096 - 1) 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#define TRF7970A_WAIT_FOR_TX_IRQ 20 1348c2ecf20Sopenharmony_ci#define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 20 1358c2ecf20Sopenharmony_ci#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 20 1368c2ecf20Sopenharmony_ci#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 40 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* Guard times for various RF technologies (in us) */ 1398c2ecf20Sopenharmony_ci#define TRF7970A_GUARD_TIME_NFCA 5000 1408c2ecf20Sopenharmony_ci#define TRF7970A_GUARD_TIME_NFCB 5000 1418c2ecf20Sopenharmony_ci#define TRF7970A_GUARD_TIME_NFCF 20000 1428c2ecf20Sopenharmony_ci#define TRF7970A_GUARD_TIME_15693 1000 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* Quirks */ 1458c2ecf20Sopenharmony_ci/* Erratum: When reading IRQ Status register on trf7970a, we must issue a 1468c2ecf20Sopenharmony_ci * read continuous command for IRQ Status and Collision Position registers. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci#define TRF7970A_QUIRK_IRQ_STATUS_READ BIT(0) 1498c2ecf20Sopenharmony_ci#define TRF7970A_QUIRK_EN2_MUST_STAY_LOW BIT(1) 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* Direct commands */ 1528c2ecf20Sopenharmony_ci#define TRF7970A_CMD_IDLE 0x00 1538c2ecf20Sopenharmony_ci#define TRF7970A_CMD_SOFT_INIT 0x03 1548c2ecf20Sopenharmony_ci#define TRF7970A_CMD_RF_COLLISION 0x04 1558c2ecf20Sopenharmony_ci#define TRF7970A_CMD_RF_COLLISION_RESPONSE_N 0x05 1568c2ecf20Sopenharmony_ci#define TRF7970A_CMD_RF_COLLISION_RESPONSE_0 0x06 1578c2ecf20Sopenharmony_ci#define TRF7970A_CMD_FIFO_RESET 0x0f 1588c2ecf20Sopenharmony_ci#define TRF7970A_CMD_TRANSMIT_NO_CRC 0x10 1598c2ecf20Sopenharmony_ci#define TRF7970A_CMD_TRANSMIT 0x11 1608c2ecf20Sopenharmony_ci#define TRF7970A_CMD_DELAY_TRANSMIT_NO_CRC 0x12 1618c2ecf20Sopenharmony_ci#define TRF7970A_CMD_DELAY_TRANSMIT 0x13 1628c2ecf20Sopenharmony_ci#define TRF7970A_CMD_EOF 0x14 1638c2ecf20Sopenharmony_ci#define TRF7970A_CMD_CLOSE_SLOT 0x15 1648c2ecf20Sopenharmony_ci#define TRF7970A_CMD_BLOCK_RX 0x16 1658c2ecf20Sopenharmony_ci#define TRF7970A_CMD_ENABLE_RX 0x17 1668c2ecf20Sopenharmony_ci#define TRF7970A_CMD_TEST_INT_RF 0x18 1678c2ecf20Sopenharmony_ci#define TRF7970A_CMD_TEST_EXT_RF 0x19 1688c2ecf20Sopenharmony_ci#define TRF7970A_CMD_RX_GAIN_ADJUST 0x1a 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci/* Bits determining whether its a direct command or register R/W, 1718c2ecf20Sopenharmony_ci * whether to use a continuous SPI transaction or not, and the actual 1728c2ecf20Sopenharmony_ci * direct cmd opcode or regster address. 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ci#define TRF7970A_CMD_BIT_CTRL BIT(7) 1758c2ecf20Sopenharmony_ci#define TRF7970A_CMD_BIT_RW BIT(6) 1768c2ecf20Sopenharmony_ci#define TRF7970A_CMD_BIT_CONTINUOUS BIT(5) 1778c2ecf20Sopenharmony_ci#define TRF7970A_CMD_BIT_OPCODE(opcode) ((opcode) & 0x1f) 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/* Registers addresses */ 1808c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_CTRL 0x00 1818c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL 0x01 1828c2ecf20Sopenharmony_ci#define TRF7970A_ISO14443B_TX_OPTIONS 0x02 1838c2ecf20Sopenharmony_ci#define TRF7970A_ISO14443A_HIGH_BITRATE_OPTIONS 0x03 1848c2ecf20Sopenharmony_ci#define TRF7970A_TX_TIMER_SETTING_H_BYTE 0x04 1858c2ecf20Sopenharmony_ci#define TRF7970A_TX_TIMER_SETTING_L_BYTE 0x05 1868c2ecf20Sopenharmony_ci#define TRF7970A_TX_PULSE_LENGTH_CTRL 0x06 1878c2ecf20Sopenharmony_ci#define TRF7970A_RX_NO_RESPONSE_WAIT 0x07 1888c2ecf20Sopenharmony_ci#define TRF7970A_RX_WAIT_TIME 0x08 1898c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_SYS_CLK_CTRL 0x09 1908c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS 0x0a 1918c2ecf20Sopenharmony_ci#define TRF7970A_REG_IO_CTRL 0x0b 1928c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS 0x0c 1938c2ecf20Sopenharmony_ci#define TRF7970A_COLLISION_IRQ_MASK 0x0d 1948c2ecf20Sopenharmony_ci#define TRF7970A_COLLISION_POSITION 0x0e 1958c2ecf20Sopenharmony_ci#define TRF7970A_RSSI_OSC_STATUS 0x0f 1968c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1 0x10 1978c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG2 0x11 1988c2ecf20Sopenharmony_ci#define TRF7970A_RAM1 0x12 1998c2ecf20Sopenharmony_ci#define TRF7970A_RAM2 0x13 2008c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS 0x14 2018c2ecf20Sopenharmony_ci#define TRF7970A_NFC_LOW_FIELD_LEVEL 0x16 2028c2ecf20Sopenharmony_ci#define TRF7970A_NFCID1 0x17 2038c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL 0x18 2048c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL 0x19 2058c2ecf20Sopenharmony_ci#define TRF7970A_TEST_REGISTER1 0x1a 2068c2ecf20Sopenharmony_ci#define TRF7970A_TEST_REGISTER2 0x1b 2078c2ecf20Sopenharmony_ci#define TRF7970A_FIFO_STATUS 0x1c 2088c2ecf20Sopenharmony_ci#define TRF7970A_TX_LENGTH_BYTE1 0x1d 2098c2ecf20Sopenharmony_ci#define TRF7970A_TX_LENGTH_BYTE2 0x1e 2108c2ecf20Sopenharmony_ci#define TRF7970A_FIFO_IO_REGISTER 0x1f 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* Chip Status Control Register Bits */ 2138c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_VRS5_3 BIT(0) 2148c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_REC_ON BIT(1) 2158c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_AGC_ON BIT(2) 2168c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_PM_ON BIT(3) 2178c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_RF_PWR BIT(4) 2188c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_RF_ON BIT(5) 2198c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_DIRECT BIT(6) 2208c2ecf20Sopenharmony_ci#define TRF7970A_CHIP_STATUS_STBY BIT(7) 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* ISO Control Register Bits */ 2238c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_SGL_1OF4_662 0x00 2248c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_SGL_1OF256_662 0x01 2258c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648 0x02 2268c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_SGL_1OF256_2648 0x03 2278c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_DBL_1OF4_667a 0x04 2288c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_DBL_1OF256_667 0x05 2298c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_DBL_1OF4_2669 0x06 2308c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_15693_DBL_1OF256_2669 0x07 2318c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443A_106 0x08 2328c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443A_212 0x09 2338c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443A_424 0x0a 2348c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443A_848 0x0b 2358c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443B_106 0x0c 2368c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443B_212 0x0d 2378c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443B_424 0x0e 2388c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_14443B_848 0x0f 2398c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_FELICA_212 0x1a 2408c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_FELICA_424 0x1b 2418c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_NFCA_106 0x01 2428c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_NFCF_212 0x02 2438c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_NFCF_424 0x03 2448c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_CE_14443A 0x00 2458c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_CE_14443B 0x01 2468c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_CE BIT(2) 2478c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_ACTIVE BIT(3) 2488c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_INITIATOR BIT(4) 2498c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE BIT(5) 2508c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_RFID BIT(5) 2518c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_DIR_MODE BIT(6) 2528c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_RX_CRC_N BIT(7) /* true == No CRC */ 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci#define TRF7970A_ISO_CTRL_RFID_SPEED_MASK 0x1f 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* Modulator and SYS_CLK Control Register Bits */ 2578c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH(n) ((n) & 0x7) 2588c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK10 (TRF7970A_MODULATOR_DEPTH(0)) 2598c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_OOK (TRF7970A_MODULATOR_DEPTH(1)) 2608c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK7 (TRF7970A_MODULATOR_DEPTH(2)) 2618c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK8_5 (TRF7970A_MODULATOR_DEPTH(3)) 2628c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK13 (TRF7970A_MODULATOR_DEPTH(4)) 2638c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK16 (TRF7970A_MODULATOR_DEPTH(5)) 2648c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK22 (TRF7970A_MODULATOR_DEPTH(6)) 2658c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_DEPTH_ASK30 (TRF7970A_MODULATOR_DEPTH(7)) 2668c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_EN_ANA BIT(3) 2678c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_CLK(n) (((n) & 0x3) << 4) 2688c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_CLK_DISABLED (TRF7970A_MODULATOR_CLK(0)) 2698c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_CLK_3_6 (TRF7970A_MODULATOR_CLK(1)) 2708c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_CLK_6_13 (TRF7970A_MODULATOR_CLK(2)) 2718c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_CLK_13_27 (TRF7970A_MODULATOR_CLK(3)) 2728c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_EN_OOK BIT(6) 2738c2ecf20Sopenharmony_ci#define TRF7970A_MODULATOR_27MHZ BIT(7) 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_NO_LIM BIT(0) 2768c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_AGCR BIT(1) 2778c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_GD_0DB (0x0 << 2) 2788c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_GD_5DB (0x1 << 2) 2798c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_GD_10DB (0x2 << 2) 2808c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_GD_15DB (0x3 << 2) 2818c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_HBT BIT(4) 2828c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_M848 BIT(5) 2838c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_C424 BIT(6) 2848c2ecf20Sopenharmony_ci#define TRF7970A_RX_SPECIAL_SETTINGS_C212 BIT(7) 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#define TRF7970A_REG_IO_CTRL_VRS(v) ((v) & 0x07) 2878c2ecf20Sopenharmony_ci#define TRF7970A_REG_IO_CTRL_IO_LOW BIT(5) 2888c2ecf20Sopenharmony_ci#define TRF7970A_REG_IO_CTRL_EN_EXT_PA BIT(6) 2898c2ecf20Sopenharmony_ci#define TRF7970A_REG_IO_CTRL_AUTO_REG BIT(7) 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci/* IRQ Status Register Bits */ 2928c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_NORESP BIT(0) /* ISO15693 only */ 2938c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_NFC_COL_ERROR BIT(0) 2948c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_COL BIT(1) 2958c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR BIT(2) 2968c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_NFC_RF BIT(2) 2978c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_PARITY_ERROR BIT(3) 2988c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_NFC_SDD BIT(3) 2998c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_CRC_ERROR BIT(4) 3008c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_NFC_PROTO_ERROR BIT(4) 3018c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_FIFO BIT(5) 3028c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_SRX BIT(6) 3038c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_TX BIT(7) 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#define TRF7970A_IRQ_STATUS_ERROR \ 3068c2ecf20Sopenharmony_ci (TRF7970A_IRQ_STATUS_COL | \ 3078c2ecf20Sopenharmony_ci TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR | \ 3088c2ecf20Sopenharmony_ci TRF7970A_IRQ_STATUS_PARITY_ERROR | \ 3098c2ecf20Sopenharmony_ci TRF7970A_IRQ_STATUS_CRC_ERROR) 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci#define TRF7970A_RSSI_OSC_STATUS_RSSI_MASK (BIT(2) | BIT(1) | BIT(0)) 3128c2ecf20Sopenharmony_ci#define TRF7970A_RSSI_OSC_STATUS_RSSI_X_MASK (BIT(5) | BIT(4) | BIT(3)) 3138c2ecf20Sopenharmony_ci#define TRF7970A_RSSI_OSC_STATUS_RSSI_OSC_OK BIT(6) 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1_COL_7_6 BIT(0) 3168c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL BIT(1) 3178c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX BIT(2) 3188c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1_SP_DIR_MODE BIT(3) 3198c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1_NEXT_SLOT_37US BIT(4) 3208c2ecf20Sopenharmony_ci#define TRF7970A_SPECIAL_FCN_REG1_PAR43 BIT(5) 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_124 (0x0 << 2) 3238c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_120 (0x1 << 2) 3248c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_112 (0x2 << 2) 3258c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 (0x3 << 2) 3268c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_4 0x0 3278c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_8 0x1 3288c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_16 0x2 3298c2ecf20Sopenharmony_ci#define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32 0x3 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci#define TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(v) ((v) & 0x07) 3328c2ecf20Sopenharmony_ci#define TRF7970A_NFC_LOW_FIELD_LEVEL_CLEX_DIS BIT(7) 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL_RFDET(v) ((v) & 0x07) 3358c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL_HI_RF BIT(3) 3368c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL_SDD_EN BIT(5) 3378c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL_LD_S_4BYTES (0x0 << 6) 3388c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL_LD_S_7BYTES (0x1 << 6) 3398c2ecf20Sopenharmony_ci#define TRF7970A_NFC_TARGET_LEVEL_LD_S_10BYTES (0x2 << 6) 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106 BIT(0) 3428c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212 BIT(1) 3438c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424 (BIT(0) | BIT(1)) 3448c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B BIT(2) 3458c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 BIT(3) 3468c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_FELICA BIT(4) 3478c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_RF_L BIT(6) 3488c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_RF_H BIT(7) 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_106A \ 3518c2ecf20Sopenharmony_ci (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ 3528c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ 3538c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 | \ 3548c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106) 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_106B \ 3578c2ecf20Sopenharmony_ci (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ 3588c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ 3598c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B | \ 3608c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106) 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_212F \ 3638c2ecf20Sopenharmony_ci (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ 3648c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ 3658c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_FELICA | \ 3668c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212) 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci#define TRF79070A_NFC_TARGET_PROTOCOL_424F \ 3698c2ecf20Sopenharmony_ci (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ 3708c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ 3718c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_FELICA | \ 3728c2ecf20Sopenharmony_ci TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424) 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci#define TRF7970A_FIFO_STATUS_OVERFLOW BIT(7) 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci/* NFC (ISO/IEC 14443A) Type 2 Tag commands */ 3778c2ecf20Sopenharmony_ci#define NFC_T2T_CMD_READ 0x30 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci/* ISO 15693 commands codes */ 3808c2ecf20Sopenharmony_ci#define ISO15693_CMD_INVENTORY 0x01 3818c2ecf20Sopenharmony_ci#define ISO15693_CMD_READ_SINGLE_BLOCK 0x20 3828c2ecf20Sopenharmony_ci#define ISO15693_CMD_WRITE_SINGLE_BLOCK 0x21 3838c2ecf20Sopenharmony_ci#define ISO15693_CMD_LOCK_BLOCK 0x22 3848c2ecf20Sopenharmony_ci#define ISO15693_CMD_READ_MULTIPLE_BLOCK 0x23 3858c2ecf20Sopenharmony_ci#define ISO15693_CMD_WRITE_MULTIPLE_BLOCK 0x24 3868c2ecf20Sopenharmony_ci#define ISO15693_CMD_SELECT 0x25 3878c2ecf20Sopenharmony_ci#define ISO15693_CMD_RESET_TO_READY 0x26 3888c2ecf20Sopenharmony_ci#define ISO15693_CMD_WRITE_AFI 0x27 3898c2ecf20Sopenharmony_ci#define ISO15693_CMD_LOCK_AFI 0x28 3908c2ecf20Sopenharmony_ci#define ISO15693_CMD_WRITE_DSFID 0x29 3918c2ecf20Sopenharmony_ci#define ISO15693_CMD_LOCK_DSFID 0x2a 3928c2ecf20Sopenharmony_ci#define ISO15693_CMD_GET_SYSTEM_INFO 0x2b 3938c2ecf20Sopenharmony_ci#define ISO15693_CMD_GET_MULTIPLE_BLOCK_SECURITY_STATUS 0x2c 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* ISO 15693 request and response flags */ 3968c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_SUB_CARRIER BIT(0) 3978c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_DATA_RATE BIT(1) 3988c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_INVENTORY BIT(2) 3998c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_PROTOCOL_EXT BIT(3) 4008c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_SELECT BIT(4) 4018c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_AFI BIT(4) 4028c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_ADDRESS BIT(5) 4038c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_NB_SLOTS BIT(5) 4048c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_OPTION BIT(6) 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci#define ISO15693_REQ_FLAG_SPEED_MASK \ 4078c2ecf20Sopenharmony_ci (ISO15693_REQ_FLAG_SUB_CARRIER | ISO15693_REQ_FLAG_DATA_RATE) 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cienum trf7970a_state { 4108c2ecf20Sopenharmony_ci TRF7970A_ST_PWR_OFF, 4118c2ecf20Sopenharmony_ci TRF7970A_ST_RF_OFF, 4128c2ecf20Sopenharmony_ci TRF7970A_ST_IDLE, 4138c2ecf20Sopenharmony_ci TRF7970A_ST_IDLE_RX_BLOCKED, 4148c2ecf20Sopenharmony_ci TRF7970A_ST_WAIT_FOR_TX_FIFO, 4158c2ecf20Sopenharmony_ci TRF7970A_ST_WAIT_FOR_RX_DATA, 4168c2ecf20Sopenharmony_ci TRF7970A_ST_WAIT_FOR_RX_DATA_CONT, 4178c2ecf20Sopenharmony_ci TRF7970A_ST_WAIT_TO_ISSUE_EOF, 4188c2ecf20Sopenharmony_ci TRF7970A_ST_LISTENING, 4198c2ecf20Sopenharmony_ci TRF7970A_ST_LISTENING_MD, 4208c2ecf20Sopenharmony_ci TRF7970A_ST_MAX 4218c2ecf20Sopenharmony_ci}; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistruct trf7970a { 4248c2ecf20Sopenharmony_ci enum trf7970a_state state; 4258c2ecf20Sopenharmony_ci struct device *dev; 4268c2ecf20Sopenharmony_ci struct spi_device *spi; 4278c2ecf20Sopenharmony_ci struct regulator *regulator; 4288c2ecf20Sopenharmony_ci struct nfc_digital_dev *ddev; 4298c2ecf20Sopenharmony_ci u32 quirks; 4308c2ecf20Sopenharmony_ci bool is_initiator; 4318c2ecf20Sopenharmony_ci bool aborting; 4328c2ecf20Sopenharmony_ci struct sk_buff *tx_skb; 4338c2ecf20Sopenharmony_ci struct sk_buff *rx_skb; 4348c2ecf20Sopenharmony_ci nfc_digital_cmd_complete_t cb; 4358c2ecf20Sopenharmony_ci void *cb_arg; 4368c2ecf20Sopenharmony_ci u8 chip_status_ctrl; 4378c2ecf20Sopenharmony_ci u8 iso_ctrl; 4388c2ecf20Sopenharmony_ci u8 iso_ctrl_tech; 4398c2ecf20Sopenharmony_ci u8 modulator_sys_clk_ctrl; 4408c2ecf20Sopenharmony_ci u8 special_fcn_reg1; 4418c2ecf20Sopenharmony_ci u8 io_ctrl; 4428c2ecf20Sopenharmony_ci unsigned int guard_time; 4438c2ecf20Sopenharmony_ci int technology; 4448c2ecf20Sopenharmony_ci int framing; 4458c2ecf20Sopenharmony_ci u8 md_rf_tech; 4468c2ecf20Sopenharmony_ci u8 tx_cmd; 4478c2ecf20Sopenharmony_ci bool issue_eof; 4488c2ecf20Sopenharmony_ci struct gpio_desc *en_gpiod; 4498c2ecf20Sopenharmony_ci struct gpio_desc *en2_gpiod; 4508c2ecf20Sopenharmony_ci struct mutex lock; 4518c2ecf20Sopenharmony_ci unsigned int timeout; 4528c2ecf20Sopenharmony_ci bool ignore_timeout; 4538c2ecf20Sopenharmony_ci struct delayed_work timeout_work; 4548c2ecf20Sopenharmony_ci}; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistatic int trf7970a_cmd(struct trf7970a *trf, u8 opcode) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci u8 cmd = TRF7970A_CMD_BIT_CTRL | TRF7970A_CMD_BIT_OPCODE(opcode); 4598c2ecf20Sopenharmony_ci int ret; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "cmd: 0x%x\n", cmd); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci ret = spi_write(trf->spi, &cmd, 1); 4648c2ecf20Sopenharmony_ci if (ret) 4658c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - cmd: 0x%x, ret: %d\n", __func__, cmd, 4668c2ecf20Sopenharmony_ci ret); 4678c2ecf20Sopenharmony_ci return ret; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic int trf7970a_read(struct trf7970a *trf, u8 reg, u8 *val) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci u8 addr = TRF7970A_CMD_BIT_RW | reg; 4738c2ecf20Sopenharmony_ci int ret; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci ret = spi_write_then_read(trf->spi, &addr, 1, val, 1); 4768c2ecf20Sopenharmony_ci if (ret) 4778c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - addr: 0x%x, ret: %d\n", __func__, addr, 4788c2ecf20Sopenharmony_ci ret); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "read(0x%x): 0x%x\n", addr, *val); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci return ret; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int trf7970a_read_cont(struct trf7970a *trf, u8 reg, u8 *buf, 4868c2ecf20Sopenharmony_ci size_t len) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci u8 addr = reg | TRF7970A_CMD_BIT_RW | TRF7970A_CMD_BIT_CONTINUOUS; 4898c2ecf20Sopenharmony_ci struct spi_transfer t[2]; 4908c2ecf20Sopenharmony_ci struct spi_message m; 4918c2ecf20Sopenharmony_ci int ret; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "read_cont(0x%x, %zd)\n", addr, len); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci spi_message_init(&m); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci memset(&t, 0, sizeof(t)); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci t[0].tx_buf = &addr; 5008c2ecf20Sopenharmony_ci t[0].len = sizeof(addr); 5018c2ecf20Sopenharmony_ci spi_message_add_tail(&t[0], &m); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci t[1].rx_buf = buf; 5048c2ecf20Sopenharmony_ci t[1].len = len; 5058c2ecf20Sopenharmony_ci spi_message_add_tail(&t[1], &m); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci ret = spi_sync(trf->spi, &m); 5088c2ecf20Sopenharmony_ci if (ret) 5098c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - addr: 0x%x, ret: %d\n", __func__, addr, 5108c2ecf20Sopenharmony_ci ret); 5118c2ecf20Sopenharmony_ci return ret; 5128c2ecf20Sopenharmony_ci} 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_cistatic int trf7970a_write(struct trf7970a *trf, u8 reg, u8 val) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci u8 buf[2] = { reg, val }; 5178c2ecf20Sopenharmony_ci int ret; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "write(0x%x): 0x%x\n", reg, val); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci ret = spi_write(trf->spi, buf, 2); 5228c2ecf20Sopenharmony_ci if (ret) 5238c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - write: 0x%x 0x%x, ret: %d\n", __func__, 5248c2ecf20Sopenharmony_ci buf[0], buf[1], ret); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci return ret; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci int ret; 5328c2ecf20Sopenharmony_ci u8 buf[2]; 5338c2ecf20Sopenharmony_ci u8 addr; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci addr = TRF7970A_IRQ_STATUS | TRF7970A_CMD_BIT_RW; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (trf->quirks & TRF7970A_QUIRK_IRQ_STATUS_READ) { 5388c2ecf20Sopenharmony_ci addr |= TRF7970A_CMD_BIT_CONTINUOUS; 5398c2ecf20Sopenharmony_ci ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2); 5408c2ecf20Sopenharmony_ci } else { 5418c2ecf20Sopenharmony_ci ret = spi_write_then_read(trf->spi, &addr, 1, buf, 1); 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (ret) 5458c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - irqstatus: Status read failed: %d\n", 5468c2ecf20Sopenharmony_ci __func__, ret); 5478c2ecf20Sopenharmony_ci else 5488c2ecf20Sopenharmony_ci *status = buf[0]; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci return ret; 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic int trf7970a_read_target_proto(struct trf7970a *trf, u8 *target_proto) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci int ret; 5568c2ecf20Sopenharmony_ci u8 buf[2]; 5578c2ecf20Sopenharmony_ci u8 addr; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci addr = TRF79070A_NFC_TARGET_PROTOCOL | TRF7970A_CMD_BIT_RW | 5608c2ecf20Sopenharmony_ci TRF7970A_CMD_BIT_CONTINUOUS; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2); 5638c2ecf20Sopenharmony_ci if (ret) 5648c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - target_proto: Read failed: %d\n", 5658c2ecf20Sopenharmony_ci __func__, ret); 5668c2ecf20Sopenharmony_ci else 5678c2ecf20Sopenharmony_ci *target_proto = buf[0]; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci return ret; 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic int trf7970a_mode_detect(struct trf7970a *trf, u8 *rf_tech) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci int ret; 5758c2ecf20Sopenharmony_ci u8 target_proto, tech; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci ret = trf7970a_read_target_proto(trf, &target_proto); 5788c2ecf20Sopenharmony_ci if (ret) 5798c2ecf20Sopenharmony_ci return ret; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci switch (target_proto) { 5828c2ecf20Sopenharmony_ci case TRF79070A_NFC_TARGET_PROTOCOL_106A: 5838c2ecf20Sopenharmony_ci tech = NFC_DIGITAL_RF_TECH_106A; 5848c2ecf20Sopenharmony_ci break; 5858c2ecf20Sopenharmony_ci case TRF79070A_NFC_TARGET_PROTOCOL_106B: 5868c2ecf20Sopenharmony_ci tech = NFC_DIGITAL_RF_TECH_106B; 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci case TRF79070A_NFC_TARGET_PROTOCOL_212F: 5898c2ecf20Sopenharmony_ci tech = NFC_DIGITAL_RF_TECH_212F; 5908c2ecf20Sopenharmony_ci break; 5918c2ecf20Sopenharmony_ci case TRF79070A_NFC_TARGET_PROTOCOL_424F: 5928c2ecf20Sopenharmony_ci tech = NFC_DIGITAL_RF_TECH_424F; 5938c2ecf20Sopenharmony_ci break; 5948c2ecf20Sopenharmony_ci default: 5958c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "%s - mode_detect: target_proto: 0x%x\n", 5968c2ecf20Sopenharmony_ci __func__, target_proto); 5978c2ecf20Sopenharmony_ci return -EIO; 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci *rf_tech = tech; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci return ret; 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic void trf7970a_send_upstream(struct trf7970a *trf) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci dev_kfree_skb_any(trf->tx_skb); 6088c2ecf20Sopenharmony_ci trf->tx_skb = NULL; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci if (trf->rx_skb && !IS_ERR(trf->rx_skb) && !trf->aborting) 6118c2ecf20Sopenharmony_ci print_hex_dump_debug("trf7970a rx data: ", DUMP_PREFIX_NONE, 6128c2ecf20Sopenharmony_ci 16, 1, trf->rx_skb->data, trf->rx_skb->len, 6138c2ecf20Sopenharmony_ci false); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_IDLE; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci if (trf->aborting) { 6188c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Abort process complete\n"); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (!IS_ERR(trf->rx_skb)) { 6218c2ecf20Sopenharmony_ci kfree_skb(trf->rx_skb); 6228c2ecf20Sopenharmony_ci trf->rx_skb = ERR_PTR(-ECANCELED); 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci trf->aborting = false; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci trf->cb(trf->ddev, trf->cb_arg, trf->rx_skb); 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci trf->rx_skb = NULL; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic void trf7970a_send_err_upstream(struct trf7970a *trf, int errno) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Error - state: %d, errno: %d\n", trf->state, errno); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci cancel_delayed_work(&trf->timeout_work); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci kfree_skb(trf->rx_skb); 6408c2ecf20Sopenharmony_ci trf->rx_skb = ERR_PTR(errno); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci trf7970a_send_upstream(trf); 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb, 6468c2ecf20Sopenharmony_ci unsigned int len, u8 *prefix, 6478c2ecf20Sopenharmony_ci unsigned int prefix_len) 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci struct spi_transfer t[2]; 6508c2ecf20Sopenharmony_ci struct spi_message m; 6518c2ecf20Sopenharmony_ci unsigned int timeout; 6528c2ecf20Sopenharmony_ci int ret; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci print_hex_dump_debug("trf7970a tx data: ", DUMP_PREFIX_NONE, 6558c2ecf20Sopenharmony_ci 16, 1, skb->data, len, false); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci spi_message_init(&m); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci memset(&t, 0, sizeof(t)); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci t[0].tx_buf = prefix; 6628c2ecf20Sopenharmony_ci t[0].len = prefix_len; 6638c2ecf20Sopenharmony_ci spi_message_add_tail(&t[0], &m); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci t[1].tx_buf = skb->data; 6668c2ecf20Sopenharmony_ci t[1].len = len; 6678c2ecf20Sopenharmony_ci spi_message_add_tail(&t[1], &m); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci ret = spi_sync(trf->spi, &m); 6708c2ecf20Sopenharmony_ci if (ret) { 6718c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Can't send tx data: %d\n", __func__, 6728c2ecf20Sopenharmony_ci ret); 6738c2ecf20Sopenharmony_ci return ret; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci skb_pull(skb, len); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci if (skb->len > 0) { 6798c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_WAIT_FOR_TX_FIFO; 6808c2ecf20Sopenharmony_ci timeout = TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT; 6818c2ecf20Sopenharmony_ci } else { 6828c2ecf20Sopenharmony_ci if (trf->issue_eof) { 6838c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_WAIT_TO_ISSUE_EOF; 6848c2ecf20Sopenharmony_ci timeout = TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF; 6858c2ecf20Sopenharmony_ci } else { 6868c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (!trf->timeout) 6898c2ecf20Sopenharmony_ci timeout = TRF7970A_WAIT_FOR_TX_IRQ; 6908c2ecf20Sopenharmony_ci else 6918c2ecf20Sopenharmony_ci timeout = trf->timeout; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n", timeout, 6968c2ecf20Sopenharmony_ci trf->state); 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout)); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci return 0; 7018c2ecf20Sopenharmony_ci} 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistatic void trf7970a_fill_fifo(struct trf7970a *trf) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci struct sk_buff *skb = trf->tx_skb; 7068c2ecf20Sopenharmony_ci unsigned int len; 7078c2ecf20Sopenharmony_ci int ret; 7088c2ecf20Sopenharmony_ci u8 fifo_bytes; 7098c2ecf20Sopenharmony_ci u8 prefix; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); 7128c2ecf20Sopenharmony_ci if (ret) { 7138c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 7148c2ecf20Sopenharmony_ci return; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Filling FIFO - fifo_bytes: 0x%x\n", fifo_bytes); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci /* Calculate how much more data can be written to the fifo */ 7228c2ecf20Sopenharmony_ci len = TRF7970A_FIFO_SIZE - fifo_bytes; 7238c2ecf20Sopenharmony_ci if (!len) { 7248c2ecf20Sopenharmony_ci schedule_delayed_work(&trf->timeout_work, 7258c2ecf20Sopenharmony_ci msecs_to_jiffies(TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT)); 7268c2ecf20Sopenharmony_ci return; 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci len = min(skb->len, len); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci prefix = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_FIFO_IO_REGISTER; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci ret = trf7970a_transmit(trf, skb, len, &prefix, sizeof(prefix)); 7348c2ecf20Sopenharmony_ci if (ret) 7358c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 7368c2ecf20Sopenharmony_ci} 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_cistatic void trf7970a_drain_fifo(struct trf7970a *trf, u8 status) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci struct sk_buff *skb = trf->rx_skb; 7418c2ecf20Sopenharmony_ci int ret; 7428c2ecf20Sopenharmony_ci u8 fifo_bytes; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if (status & TRF7970A_IRQ_STATUS_ERROR) { 7458c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -EIO); 7468c2ecf20Sopenharmony_ci return; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); 7508c2ecf20Sopenharmony_ci if (ret) { 7518c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 7528c2ecf20Sopenharmony_ci return; 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Draining FIFO - fifo_bytes: 0x%x\n", fifo_bytes); 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci if (!fifo_bytes) 7608c2ecf20Sopenharmony_ci goto no_rx_data; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci if (fifo_bytes > skb_tailroom(skb)) { 7638c2ecf20Sopenharmony_ci skb = skb_copy_expand(skb, skb_headroom(skb), 7648c2ecf20Sopenharmony_ci max_t(int, fifo_bytes, 7658c2ecf20Sopenharmony_ci TRF7970A_RX_SKB_ALLOC_SIZE), 7668c2ecf20Sopenharmony_ci GFP_KERNEL); 7678c2ecf20Sopenharmony_ci if (!skb) { 7688c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -ENOMEM); 7698c2ecf20Sopenharmony_ci return; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci kfree_skb(trf->rx_skb); 7738c2ecf20Sopenharmony_ci trf->rx_skb = skb; 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci ret = trf7970a_read_cont(trf, TRF7970A_FIFO_IO_REGISTER, 7778c2ecf20Sopenharmony_ci skb_put(skb, fifo_bytes), fifo_bytes); 7788c2ecf20Sopenharmony_ci if (ret) { 7798c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 7808c2ecf20Sopenharmony_ci return; 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* If received Type 2 ACK/NACK, shift right 4 bits and pass up */ 7848c2ecf20Sopenharmony_ci if ((trf->framing == NFC_DIGITAL_FRAMING_NFCA_T2T) && (skb->len == 1) && 7858c2ecf20Sopenharmony_ci (trf->special_fcn_reg1 == TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX)) { 7868c2ecf20Sopenharmony_ci skb->data[0] >>= 4; 7878c2ecf20Sopenharmony_ci status = TRF7970A_IRQ_STATUS_SRX; 7888c2ecf20Sopenharmony_ci } else { 7898c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA_CONT; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); 7928c2ecf20Sopenharmony_ci if (ret) { 7938c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 7948c2ecf20Sopenharmony_ci return; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* If there are bytes in the FIFO, set status to '0' so 8008c2ecf20Sopenharmony_ci * the if stmt below doesn't fire and the driver will wait 8018c2ecf20Sopenharmony_ci * for the trf7970a to generate another RX interrupt. 8028c2ecf20Sopenharmony_ci */ 8038c2ecf20Sopenharmony_ci if (fifo_bytes) 8048c2ecf20Sopenharmony_ci status = 0; 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cino_rx_data: 8088c2ecf20Sopenharmony_ci if (status == TRF7970A_IRQ_STATUS_SRX) { /* Receive complete */ 8098c2ecf20Sopenharmony_ci trf7970a_send_upstream(trf); 8108c2ecf20Sopenharmony_ci return; 8118c2ecf20Sopenharmony_ci } 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Setting timeout for %d ms\n", 8148c2ecf20Sopenharmony_ci TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci schedule_delayed_work(&trf->timeout_work, 8178c2ecf20Sopenharmony_ci msecs_to_jiffies(TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT)); 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic irqreturn_t trf7970a_irq(int irq, void *dev_id) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci struct trf7970a *trf = dev_id; 8238c2ecf20Sopenharmony_ci int ret; 8248c2ecf20Sopenharmony_ci u8 status, fifo_bytes, iso_ctrl; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci if (trf->state == TRF7970A_ST_RF_OFF) { 8298c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 8308c2ecf20Sopenharmony_ci return IRQ_NONE; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci ret = trf7970a_read_irqstatus(trf, &status); 8348c2ecf20Sopenharmony_ci if (ret) { 8358c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 8368c2ecf20Sopenharmony_ci return IRQ_NONE; 8378c2ecf20Sopenharmony_ci } 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "IRQ - state: %d, status: 0x%x\n", trf->state, 8408c2ecf20Sopenharmony_ci status); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci if (!status) { 8438c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 8448c2ecf20Sopenharmony_ci return IRQ_NONE; 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci switch (trf->state) { 8488c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE: 8498c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE_RX_BLOCKED: 8508c2ecf20Sopenharmony_ci /* If initiator and getting interrupts caused by RF noise, 8518c2ecf20Sopenharmony_ci * turn off the receiver to avoid unnecessary interrupts. 8528c2ecf20Sopenharmony_ci * It will be turned back on in trf7970a_send_cmd() when 8538c2ecf20Sopenharmony_ci * the next command is issued. 8548c2ecf20Sopenharmony_ci */ 8558c2ecf20Sopenharmony_ci if (trf->is_initiator && (status & TRF7970A_IRQ_STATUS_ERROR)) { 8568c2ecf20Sopenharmony_ci trf7970a_cmd(trf, TRF7970A_CMD_BLOCK_RX); 8578c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_IDLE_RX_BLOCKED; 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); 8618c2ecf20Sopenharmony_ci break; 8628c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_TX_FIFO: 8638c2ecf20Sopenharmony_ci if (status & TRF7970A_IRQ_STATUS_TX) { 8648c2ecf20Sopenharmony_ci trf->ignore_timeout = 8658c2ecf20Sopenharmony_ci !cancel_delayed_work(&trf->timeout_work); 8668c2ecf20Sopenharmony_ci trf7970a_fill_fifo(trf); 8678c2ecf20Sopenharmony_ci } else { 8688c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -EIO); 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci break; 8718c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA: 8728c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: 8738c2ecf20Sopenharmony_ci if (status & TRF7970A_IRQ_STATUS_SRX) { 8748c2ecf20Sopenharmony_ci trf->ignore_timeout = 8758c2ecf20Sopenharmony_ci !cancel_delayed_work(&trf->timeout_work); 8768c2ecf20Sopenharmony_ci trf7970a_drain_fifo(trf, status); 8778c2ecf20Sopenharmony_ci } else if (status & TRF7970A_IRQ_STATUS_FIFO) { 8788c2ecf20Sopenharmony_ci ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, 8798c2ecf20Sopenharmony_ci &fifo_bytes); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (ret) 8848c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 8858c2ecf20Sopenharmony_ci else if (!fifo_bytes) 8868c2ecf20Sopenharmony_ci trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); 8878c2ecf20Sopenharmony_ci } else if ((status == TRF7970A_IRQ_STATUS_TX) || 8888c2ecf20Sopenharmony_ci (!trf->is_initiator && 8898c2ecf20Sopenharmony_ci (status == (TRF7970A_IRQ_STATUS_TX | 8908c2ecf20Sopenharmony_ci TRF7970A_IRQ_STATUS_NFC_RF)))) { 8918c2ecf20Sopenharmony_ci trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci if (!trf->timeout) { 8948c2ecf20Sopenharmony_ci trf->ignore_timeout = 8958c2ecf20Sopenharmony_ci !cancel_delayed_work(&trf->timeout_work); 8968c2ecf20Sopenharmony_ci trf->rx_skb = ERR_PTR(0); 8978c2ecf20Sopenharmony_ci trf7970a_send_upstream(trf); 8988c2ecf20Sopenharmony_ci break; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (trf->is_initiator) 9028c2ecf20Sopenharmony_ci break; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci iso_ctrl = trf->iso_ctrl; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci switch (trf->framing) { 9078c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_STANDARD: 9088c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; 9098c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; 9108c2ecf20Sopenharmony_ci trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */ 9118c2ecf20Sopenharmony_ci break; 9128c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: 9138c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT; 9148c2ecf20Sopenharmony_ci iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; 9158c2ecf20Sopenharmony_ci trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */ 9168c2ecf20Sopenharmony_ci break; 9178c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE: 9188c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, 9198c2ecf20Sopenharmony_ci TRF7970A_SPECIAL_FCN_REG1, 9208c2ecf20Sopenharmony_ci TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL); 9218c2ecf20Sopenharmony_ci if (ret) 9228c2ecf20Sopenharmony_ci goto err_unlock_exit; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci trf->special_fcn_reg1 = 9258c2ecf20Sopenharmony_ci TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL; 9268c2ecf20Sopenharmony_ci break; 9278c2ecf20Sopenharmony_ci default: 9288c2ecf20Sopenharmony_ci break; 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci if (iso_ctrl != trf->iso_ctrl) { 9328c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, 9338c2ecf20Sopenharmony_ci iso_ctrl); 9348c2ecf20Sopenharmony_ci if (ret) 9358c2ecf20Sopenharmony_ci goto err_unlock_exit; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci trf->iso_ctrl = iso_ctrl; 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci } else { 9408c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -EIO); 9418c2ecf20Sopenharmony_ci } 9428c2ecf20Sopenharmony_ci break; 9438c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_TO_ISSUE_EOF: 9448c2ecf20Sopenharmony_ci if (status != TRF7970A_IRQ_STATUS_TX) 9458c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -EIO); 9468c2ecf20Sopenharmony_ci break; 9478c2ecf20Sopenharmony_ci case TRF7970A_ST_LISTENING: 9488c2ecf20Sopenharmony_ci if (status & TRF7970A_IRQ_STATUS_SRX) { 9498c2ecf20Sopenharmony_ci trf->ignore_timeout = 9508c2ecf20Sopenharmony_ci !cancel_delayed_work(&trf->timeout_work); 9518c2ecf20Sopenharmony_ci trf7970a_drain_fifo(trf, status); 9528c2ecf20Sopenharmony_ci } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) { 9538c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -EIO); 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci break; 9568c2ecf20Sopenharmony_ci case TRF7970A_ST_LISTENING_MD: 9578c2ecf20Sopenharmony_ci if (status & TRF7970A_IRQ_STATUS_SRX) { 9588c2ecf20Sopenharmony_ci trf->ignore_timeout = 9598c2ecf20Sopenharmony_ci !cancel_delayed_work(&trf->timeout_work); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci ret = trf7970a_mode_detect(trf, &trf->md_rf_tech); 9628c2ecf20Sopenharmony_ci if (ret) { 9638c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 9648c2ecf20Sopenharmony_ci } else { 9658c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_LISTENING; 9668c2ecf20Sopenharmony_ci trf7970a_drain_fifo(trf, status); 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) { 9698c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -EIO); 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci break; 9728c2ecf20Sopenharmony_ci default: 9738c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Driver in invalid state: %d\n", 9748c2ecf20Sopenharmony_ci __func__, trf->state); 9758c2ecf20Sopenharmony_ci } 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cierr_unlock_exit: 9788c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 9798c2ecf20Sopenharmony_ci return IRQ_HANDLED; 9808c2ecf20Sopenharmony_ci} 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cistatic void trf7970a_issue_eof(struct trf7970a *trf) 9838c2ecf20Sopenharmony_ci{ 9848c2ecf20Sopenharmony_ci int ret; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Issuing EOF\n"); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); 9898c2ecf20Sopenharmony_ci if (ret) 9908c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_EOF); 9938c2ecf20Sopenharmony_ci if (ret) 9948c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, ret); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Setting timeout for %d ms, state: %d\n", 9998c2ecf20Sopenharmony_ci trf->timeout, trf->state); 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci schedule_delayed_work(&trf->timeout_work, 10028c2ecf20Sopenharmony_ci msecs_to_jiffies(trf->timeout)); 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic void trf7970a_timeout_work_handler(struct work_struct *work) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci struct trf7970a *trf = container_of(work, struct trf7970a, 10088c2ecf20Sopenharmony_ci timeout_work.work); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Timeout - state: %d, ignore_timeout: %d\n", 10118c2ecf20Sopenharmony_ci trf->state, trf->ignore_timeout); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci if (trf->ignore_timeout) 10168c2ecf20Sopenharmony_ci trf->ignore_timeout = false; 10178c2ecf20Sopenharmony_ci else if (trf->state == TRF7970A_ST_WAIT_FOR_RX_DATA_CONT) 10188c2ecf20Sopenharmony_ci trf7970a_drain_fifo(trf, TRF7970A_IRQ_STATUS_SRX); 10198c2ecf20Sopenharmony_ci else if (trf->state == TRF7970A_ST_WAIT_TO_ISSUE_EOF) 10208c2ecf20Sopenharmony_ci trf7970a_issue_eof(trf); 10218c2ecf20Sopenharmony_ci else 10228c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -ETIMEDOUT); 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 10258c2ecf20Sopenharmony_ci} 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_cistatic int trf7970a_init(struct trf7970a *trf) 10288c2ecf20Sopenharmony_ci{ 10298c2ecf20Sopenharmony_ci int ret; 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Initializing device - state: %d\n", trf->state); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_SOFT_INIT); 10348c2ecf20Sopenharmony_ci if (ret) 10358c2ecf20Sopenharmony_ci goto err_out; 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_IDLE); 10388c2ecf20Sopenharmony_ci if (ret) 10398c2ecf20Sopenharmony_ci goto err_out; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL, 10428c2ecf20Sopenharmony_ci trf->io_ctrl | TRF7970A_REG_IO_CTRL_VRS(0x1)); 10438c2ecf20Sopenharmony_ci if (ret) 10448c2ecf20Sopenharmony_ci goto err_out; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); 10478c2ecf20Sopenharmony_ci if (ret) 10488c2ecf20Sopenharmony_ci goto err_out; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 10558c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl); 10568c2ecf20Sopenharmony_ci if (ret) 10578c2ecf20Sopenharmony_ci goto err_out; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS, 10608c2ecf20Sopenharmony_ci TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 | 10618c2ecf20Sopenharmony_ci TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32); 10628c2ecf20Sopenharmony_ci if (ret) 10638c2ecf20Sopenharmony_ci goto err_out; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_SPECIAL_FCN_REG1, 0); 10668c2ecf20Sopenharmony_ci if (ret) 10678c2ecf20Sopenharmony_ci goto err_out; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci trf->special_fcn_reg1 = 0; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci trf->iso_ctrl = 0xff; 10728c2ecf20Sopenharmony_ci return 0; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_cierr_out: 10758c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Couldn't init device: %d\n", ret); 10768c2ecf20Sopenharmony_ci return ret; 10778c2ecf20Sopenharmony_ci} 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_cistatic void trf7970a_switch_rf_off(struct trf7970a *trf) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci if ((trf->state == TRF7970A_ST_PWR_OFF) || 10828c2ecf20Sopenharmony_ci (trf->state == TRF7970A_ST_RF_OFF)) 10838c2ecf20Sopenharmony_ci return; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Switching rf off\n"); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci trf->aborting = false; 10928c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_RF_OFF; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(trf->dev); 10958c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(trf->dev); 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cistatic int trf7970a_switch_rf_on(struct trf7970a *trf) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci int ret; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Switching rf on\n"); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci pm_runtime_get_sync(trf->dev); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (trf->state != TRF7970A_ST_RF_OFF) { /* Power on, RF off */ 11078c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Incorrect state: %d\n", __func__, 11088c2ecf20Sopenharmony_ci trf->state); 11098c2ecf20Sopenharmony_ci return -EINVAL; 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci ret = trf7970a_init(trf); 11138c2ecf20Sopenharmony_ci if (ret) { 11148c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Can't initialize: %d\n", __func__, ret); 11158c2ecf20Sopenharmony_ci return ret; 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_IDLE; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci return 0; 11218c2ecf20Sopenharmony_ci} 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cistatic int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 11268c2ecf20Sopenharmony_ci int ret = 0; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on); 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci if (on) { 11338c2ecf20Sopenharmony_ci switch (trf->state) { 11348c2ecf20Sopenharmony_ci case TRF7970A_ST_PWR_OFF: 11358c2ecf20Sopenharmony_ci case TRF7970A_ST_RF_OFF: 11368c2ecf20Sopenharmony_ci ret = trf7970a_switch_rf_on(trf); 11378c2ecf20Sopenharmony_ci break; 11388c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE: 11398c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE_RX_BLOCKED: 11408c2ecf20Sopenharmony_ci break; 11418c2ecf20Sopenharmony_ci default: 11428c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Invalid request: %d %d\n", 11438c2ecf20Sopenharmony_ci __func__, trf->state, on); 11448c2ecf20Sopenharmony_ci trf7970a_switch_rf_off(trf); 11458c2ecf20Sopenharmony_ci ret = -EINVAL; 11468c2ecf20Sopenharmony_ci } 11478c2ecf20Sopenharmony_ci } else { 11488c2ecf20Sopenharmony_ci switch (trf->state) { 11498c2ecf20Sopenharmony_ci case TRF7970A_ST_PWR_OFF: 11508c2ecf20Sopenharmony_ci case TRF7970A_ST_RF_OFF: 11518c2ecf20Sopenharmony_ci break; 11528c2ecf20Sopenharmony_ci default: 11538c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Invalid request: %d %d\n", 11548c2ecf20Sopenharmony_ci __func__, trf->state, on); 11558c2ecf20Sopenharmony_ci ret = -EINVAL; 11568c2ecf20Sopenharmony_ci fallthrough; 11578c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE: 11588c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE_RX_BLOCKED: 11598c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA: 11608c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: 11618c2ecf20Sopenharmony_ci trf7970a_switch_rf_off(trf); 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 11668c2ecf20Sopenharmony_ci return ret; 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci int ret = 0; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "rf technology: %d\n", tech); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci switch (tech) { 11768c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_106A: 11778c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443A_106; 11788c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 11798c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 11808c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_OOK; 11818c2ecf20Sopenharmony_ci trf->guard_time = TRF7970A_GUARD_TIME_NFCA; 11828c2ecf20Sopenharmony_ci break; 11838c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_106B: 11848c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443B_106; 11858c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 11868c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 11878c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_ASK10; 11888c2ecf20Sopenharmony_ci trf->guard_time = TRF7970A_GUARD_TIME_NFCB; 11898c2ecf20Sopenharmony_ci break; 11908c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_212F: 11918c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_212; 11928c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 11938c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 11948c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_ASK10; 11958c2ecf20Sopenharmony_ci trf->guard_time = TRF7970A_GUARD_TIME_NFCF; 11968c2ecf20Sopenharmony_ci break; 11978c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_424F: 11988c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_424; 11998c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 12008c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 12018c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_ASK10; 12028c2ecf20Sopenharmony_ci trf->guard_time = TRF7970A_GUARD_TIME_NFCF; 12038c2ecf20Sopenharmony_ci break; 12048c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_ISO15693: 12058c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; 12068c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 12078c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 12088c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_OOK; 12098c2ecf20Sopenharmony_ci trf->guard_time = TRF7970A_GUARD_TIME_15693; 12108c2ecf20Sopenharmony_ci break; 12118c2ecf20Sopenharmony_ci default: 12128c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); 12138c2ecf20Sopenharmony_ci return -EINVAL; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci trf->technology = tech; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci /* If in initiator mode and not changing the RF tech due to a 12198c2ecf20Sopenharmony_ci * PSL sequence (indicated by 'trf->iso_ctrl == 0xff' from 12208c2ecf20Sopenharmony_ci * trf7970a_init()), clear the NFC Target Detection Level register 12218c2ecf20Sopenharmony_ci * due to erratum. 12228c2ecf20Sopenharmony_ci */ 12238c2ecf20Sopenharmony_ci if (trf->iso_ctrl == 0xff) 12248c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci return ret; 12278c2ecf20Sopenharmony_ci} 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_cistatic int trf7970a_is_rf_field(struct trf7970a *trf, bool *is_rf_field) 12308c2ecf20Sopenharmony_ci{ 12318c2ecf20Sopenharmony_ci int ret; 12328c2ecf20Sopenharmony_ci u8 rssi; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, 12358c2ecf20Sopenharmony_ci trf->chip_status_ctrl | 12368c2ecf20Sopenharmony_ci TRF7970A_CHIP_STATUS_REC_ON); 12378c2ecf20Sopenharmony_ci if (ret) 12388c2ecf20Sopenharmony_ci return ret; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_TEST_EXT_RF); 12418c2ecf20Sopenharmony_ci if (ret) 12428c2ecf20Sopenharmony_ci return ret; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci usleep_range(50, 60); 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci ret = trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi); 12478c2ecf20Sopenharmony_ci if (ret) 12488c2ecf20Sopenharmony_ci return ret; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, 12518c2ecf20Sopenharmony_ci trf->chip_status_ctrl); 12528c2ecf20Sopenharmony_ci if (ret) 12538c2ecf20Sopenharmony_ci return ret; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci if (rssi & TRF7970A_RSSI_OSC_STATUS_RSSI_MASK) 12568c2ecf20Sopenharmony_ci *is_rf_field = true; 12578c2ecf20Sopenharmony_ci else 12588c2ecf20Sopenharmony_ci *is_rf_field = false; 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci return 0; 12618c2ecf20Sopenharmony_ci} 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_cistatic int trf7970a_in_config_framing(struct trf7970a *trf, int framing) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci u8 iso_ctrl = trf->iso_ctrl_tech; 12668c2ecf20Sopenharmony_ci bool is_rf_field = false; 12678c2ecf20Sopenharmony_ci int ret; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "framing: %d\n", framing); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci switch (framing) { 12728c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_SHORT: 12738c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_STANDARD: 12748c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; 12758c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; 12768c2ecf20Sopenharmony_ci break; 12778c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: 12788c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_T4T: 12798c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCB: 12808c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCB_T4T: 12818c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCF: 12828c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCF_T3T: 12838c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY: 12848c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_ISO15693_T5T: 12858c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP: 12868c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP: 12878c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT; 12888c2ecf20Sopenharmony_ci iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; 12898c2ecf20Sopenharmony_ci break; 12908c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_T2T: 12918c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT; 12928c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; 12938c2ecf20Sopenharmony_ci break; 12948c2ecf20Sopenharmony_ci default: 12958c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing); 12968c2ecf20Sopenharmony_ci return -EINVAL; 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci trf->framing = framing; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) { 13028c2ecf20Sopenharmony_ci ret = trf7970a_is_rf_field(trf, &is_rf_field); 13038c2ecf20Sopenharmony_ci if (ret) 13048c2ecf20Sopenharmony_ci return ret; 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci if (is_rf_field) 13078c2ecf20Sopenharmony_ci return -EBUSY; 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci if (iso_ctrl != trf->iso_ctrl) { 13118c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 13128c2ecf20Sopenharmony_ci if (ret) 13138c2ecf20Sopenharmony_ci return ret; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci trf->iso_ctrl = iso_ctrl; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 13188c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl); 13198c2ecf20Sopenharmony_ci if (ret) 13208c2ecf20Sopenharmony_ci return ret; 13218c2ecf20Sopenharmony_ci } 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) { 13248c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, 13258c2ecf20Sopenharmony_ci trf->chip_status_ctrl | 13268c2ecf20Sopenharmony_ci TRF7970A_CHIP_STATUS_RF_ON); 13278c2ecf20Sopenharmony_ci if (ret) 13288c2ecf20Sopenharmony_ci return ret; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci usleep_range(trf->guard_time, trf->guard_time + 1000); 13338c2ecf20Sopenharmony_ci } 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci return 0; 13368c2ecf20Sopenharmony_ci} 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_cistatic int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, 13398c2ecf20Sopenharmony_ci int param) 13408c2ecf20Sopenharmony_ci{ 13418c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 13428c2ecf20Sopenharmony_ci int ret; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param); 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci trf->is_initiator = true; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci if ((trf->state == TRF7970A_ST_PWR_OFF) || 13518c2ecf20Sopenharmony_ci (trf->state == TRF7970A_ST_RF_OFF)) { 13528c2ecf20Sopenharmony_ci ret = trf7970a_switch_rf_on(trf); 13538c2ecf20Sopenharmony_ci if (ret) 13548c2ecf20Sopenharmony_ci goto err_unlock; 13558c2ecf20Sopenharmony_ci } 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci switch (type) { 13588c2ecf20Sopenharmony_ci case NFC_DIGITAL_CONFIG_RF_TECH: 13598c2ecf20Sopenharmony_ci ret = trf7970a_in_config_rf_tech(trf, param); 13608c2ecf20Sopenharmony_ci break; 13618c2ecf20Sopenharmony_ci case NFC_DIGITAL_CONFIG_FRAMING: 13628c2ecf20Sopenharmony_ci ret = trf7970a_in_config_framing(trf, param); 13638c2ecf20Sopenharmony_ci break; 13648c2ecf20Sopenharmony_ci default: 13658c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Unknown type: %d\n", type); 13668c2ecf20Sopenharmony_ci ret = -EINVAL; 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_cierr_unlock: 13708c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 13718c2ecf20Sopenharmony_ci return ret; 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic int trf7970a_is_iso15693_write_or_lock(u8 cmd) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci switch (cmd) { 13778c2ecf20Sopenharmony_ci case ISO15693_CMD_WRITE_SINGLE_BLOCK: 13788c2ecf20Sopenharmony_ci case ISO15693_CMD_LOCK_BLOCK: 13798c2ecf20Sopenharmony_ci case ISO15693_CMD_WRITE_MULTIPLE_BLOCK: 13808c2ecf20Sopenharmony_ci case ISO15693_CMD_WRITE_AFI: 13818c2ecf20Sopenharmony_ci case ISO15693_CMD_LOCK_AFI: 13828c2ecf20Sopenharmony_ci case ISO15693_CMD_WRITE_DSFID: 13838c2ecf20Sopenharmony_ci case ISO15693_CMD_LOCK_DSFID: 13848c2ecf20Sopenharmony_ci return 1; 13858c2ecf20Sopenharmony_ci default: 13868c2ecf20Sopenharmony_ci return 0; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_cistatic int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb) 13918c2ecf20Sopenharmony_ci{ 13928c2ecf20Sopenharmony_ci u8 *req = skb->data; 13938c2ecf20Sopenharmony_ci u8 special_fcn_reg1, iso_ctrl; 13948c2ecf20Sopenharmony_ci int ret; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci trf->issue_eof = false; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci /* When issuing Type 2 read command, make sure the '4_bit_RX' bit in 13998c2ecf20Sopenharmony_ci * special functions register 1 is cleared; otherwise, its a write or 14008c2ecf20Sopenharmony_ci * sector select command and '4_bit_RX' must be set. 14018c2ecf20Sopenharmony_ci * 14028c2ecf20Sopenharmony_ci * When issuing an ISO 15693 command, inspect the flags byte to see 14038c2ecf20Sopenharmony_ci * what speed to use. Also, remember if the OPTION flag is set on 14048c2ecf20Sopenharmony_ci * a Type 5 write or lock command so the driver will know that it 14058c2ecf20Sopenharmony_ci * has to send an EOF in order to get a response. 14068c2ecf20Sopenharmony_ci */ 14078c2ecf20Sopenharmony_ci if ((trf->technology == NFC_DIGITAL_RF_TECH_106A) && 14088c2ecf20Sopenharmony_ci (trf->framing == NFC_DIGITAL_FRAMING_NFCA_T2T)) { 14098c2ecf20Sopenharmony_ci if (req[0] == NFC_T2T_CMD_READ) 14108c2ecf20Sopenharmony_ci special_fcn_reg1 = 0; 14118c2ecf20Sopenharmony_ci else 14128c2ecf20Sopenharmony_ci special_fcn_reg1 = TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci if (special_fcn_reg1 != trf->special_fcn_reg1) { 14158c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_SPECIAL_FCN_REG1, 14168c2ecf20Sopenharmony_ci special_fcn_reg1); 14178c2ecf20Sopenharmony_ci if (ret) 14188c2ecf20Sopenharmony_ci return ret; 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci trf->special_fcn_reg1 = special_fcn_reg1; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci } else if (trf->technology == NFC_DIGITAL_RF_TECH_ISO15693) { 14238c2ecf20Sopenharmony_ci iso_ctrl = trf->iso_ctrl & ~TRF7970A_ISO_CTRL_RFID_SPEED_MASK; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci switch (req[0] & ISO15693_REQ_FLAG_SPEED_MASK) { 14268c2ecf20Sopenharmony_ci case 0x00: 14278c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_15693_SGL_1OF4_662; 14288c2ecf20Sopenharmony_ci break; 14298c2ecf20Sopenharmony_ci case ISO15693_REQ_FLAG_SUB_CARRIER: 14308c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_15693_DBL_1OF4_667a; 14318c2ecf20Sopenharmony_ci break; 14328c2ecf20Sopenharmony_ci case ISO15693_REQ_FLAG_DATA_RATE: 14338c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; 14348c2ecf20Sopenharmony_ci break; 14358c2ecf20Sopenharmony_ci case (ISO15693_REQ_FLAG_SUB_CARRIER | 14368c2ecf20Sopenharmony_ci ISO15693_REQ_FLAG_DATA_RATE): 14378c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_15693_DBL_1OF4_2669; 14388c2ecf20Sopenharmony_ci break; 14398c2ecf20Sopenharmony_ci } 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci if (iso_ctrl != trf->iso_ctrl) { 14428c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 14438c2ecf20Sopenharmony_ci if (ret) 14448c2ecf20Sopenharmony_ci return ret; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci trf->iso_ctrl = iso_ctrl; 14478c2ecf20Sopenharmony_ci } 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci if ((trf->framing == NFC_DIGITAL_FRAMING_ISO15693_T5T) && 14508c2ecf20Sopenharmony_ci trf7970a_is_iso15693_write_or_lock(req[1]) && 14518c2ecf20Sopenharmony_ci (req[0] & ISO15693_REQ_FLAG_OPTION)) 14528c2ecf20Sopenharmony_ci trf->issue_eof = true; 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci return 0; 14568c2ecf20Sopenharmony_ci} 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_cistatic int trf7970a_send_cmd(struct nfc_digital_dev *ddev, 14598c2ecf20Sopenharmony_ci struct sk_buff *skb, u16 timeout, 14608c2ecf20Sopenharmony_ci nfc_digital_cmd_complete_t cb, void *arg) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 14638c2ecf20Sopenharmony_ci u8 prefix[5]; 14648c2ecf20Sopenharmony_ci unsigned int len; 14658c2ecf20Sopenharmony_ci int ret; 14668c2ecf20Sopenharmony_ci u8 status; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "New request - state: %d, timeout: %d ms, len: %d\n", 14698c2ecf20Sopenharmony_ci trf->state, timeout, skb->len); 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci if (skb->len > TRF7970A_TX_MAX) 14728c2ecf20Sopenharmony_ci return -EINVAL; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci if ((trf->state != TRF7970A_ST_IDLE) && 14778c2ecf20Sopenharmony_ci (trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) { 14788c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Bogus state: %d\n", __func__, 14798c2ecf20Sopenharmony_ci trf->state); 14808c2ecf20Sopenharmony_ci ret = -EIO; 14818c2ecf20Sopenharmony_ci goto out_err; 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci if (trf->aborting) { 14858c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Abort process complete\n"); 14868c2ecf20Sopenharmony_ci trf->aborting = false; 14878c2ecf20Sopenharmony_ci ret = -ECANCELED; 14888c2ecf20Sopenharmony_ci goto out_err; 14898c2ecf20Sopenharmony_ci } 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci if (timeout) { 14928c2ecf20Sopenharmony_ci trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE, 14938c2ecf20Sopenharmony_ci GFP_KERNEL); 14948c2ecf20Sopenharmony_ci if (!trf->rx_skb) { 14958c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Can't alloc rx_skb\n"); 14968c2ecf20Sopenharmony_ci ret = -ENOMEM; 14978c2ecf20Sopenharmony_ci goto out_err; 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci } 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci if (trf->state == TRF7970A_ST_IDLE_RX_BLOCKED) { 15028c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX); 15038c2ecf20Sopenharmony_ci if (ret) 15048c2ecf20Sopenharmony_ci goto out_err; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_IDLE; 15078c2ecf20Sopenharmony_ci } 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci if (trf->is_initiator) { 15108c2ecf20Sopenharmony_ci ret = trf7970a_per_cmd_config(trf, skb); 15118c2ecf20Sopenharmony_ci if (ret) 15128c2ecf20Sopenharmony_ci goto out_err; 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci trf->ddev = ddev; 15168c2ecf20Sopenharmony_ci trf->tx_skb = skb; 15178c2ecf20Sopenharmony_ci trf->cb = cb; 15188c2ecf20Sopenharmony_ci trf->cb_arg = arg; 15198c2ecf20Sopenharmony_ci trf->timeout = timeout; 15208c2ecf20Sopenharmony_ci trf->ignore_timeout = false; 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci len = skb->len; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends 15258c2ecf20Sopenharmony_ci * on what the current framing is, the address of the TX length byte 1 15268c2ecf20Sopenharmony_ci * register (0x1d), and the 2 byte length of the data to be transmitted. 15278c2ecf20Sopenharmony_ci * That totals 5 bytes. 15288c2ecf20Sopenharmony_ci */ 15298c2ecf20Sopenharmony_ci prefix[0] = TRF7970A_CMD_BIT_CTRL | 15308c2ecf20Sopenharmony_ci TRF7970A_CMD_BIT_OPCODE(TRF7970A_CMD_FIFO_RESET); 15318c2ecf20Sopenharmony_ci prefix[1] = TRF7970A_CMD_BIT_CTRL | 15328c2ecf20Sopenharmony_ci TRF7970A_CMD_BIT_OPCODE(trf->tx_cmd); 15338c2ecf20Sopenharmony_ci prefix[2] = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_TX_LENGTH_BYTE1; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci if (trf->framing == NFC_DIGITAL_FRAMING_NFCA_SHORT) { 15368c2ecf20Sopenharmony_ci prefix[3] = 0x00; 15378c2ecf20Sopenharmony_ci prefix[4] = 0x0f; /* 7 bits */ 15388c2ecf20Sopenharmony_ci } else { 15398c2ecf20Sopenharmony_ci prefix[3] = (len & 0xf00) >> 4; 15408c2ecf20Sopenharmony_ci prefix[3] |= ((len & 0xf0) >> 4); 15418c2ecf20Sopenharmony_ci prefix[4] = ((len & 0x0f) << 4); 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci len = min_t(int, skb->len, TRF7970A_FIFO_SIZE); 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci /* Clear possible spurious interrupt */ 15478c2ecf20Sopenharmony_ci ret = trf7970a_read_irqstatus(trf, &status); 15488c2ecf20Sopenharmony_ci if (ret) 15498c2ecf20Sopenharmony_ci goto out_err; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci ret = trf7970a_transmit(trf, skb, len, prefix, sizeof(prefix)); 15528c2ecf20Sopenharmony_ci if (ret) { 15538c2ecf20Sopenharmony_ci kfree_skb(trf->rx_skb); 15548c2ecf20Sopenharmony_ci trf->rx_skb = NULL; 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ciout_err: 15588c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 15598c2ecf20Sopenharmony_ci return ret; 15608c2ecf20Sopenharmony_ci} 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_cistatic int trf7970a_tg_config_rf_tech(struct trf7970a *trf, int tech) 15638c2ecf20Sopenharmony_ci{ 15648c2ecf20Sopenharmony_ci int ret = 0; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "rf technology: %d\n", tech); 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci switch (tech) { 15698c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_106A: 15708c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | 15718c2ecf20Sopenharmony_ci TRF7970A_ISO_CTRL_NFC_CE | TRF7970A_ISO_CTRL_NFC_CE_14443A; 15728c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 15738c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 15748c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_OOK; 15758c2ecf20Sopenharmony_ci break; 15768c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_212F: 15778c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | 15788c2ecf20Sopenharmony_ci TRF7970A_ISO_CTRL_NFC_NFCF_212; 15798c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 15808c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 15818c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_ASK10; 15828c2ecf20Sopenharmony_ci break; 15838c2ecf20Sopenharmony_ci case NFC_DIGITAL_RF_TECH_424F: 15848c2ecf20Sopenharmony_ci trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | 15858c2ecf20Sopenharmony_ci TRF7970A_ISO_CTRL_NFC_NFCF_424; 15868c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 15878c2ecf20Sopenharmony_ci (trf->modulator_sys_clk_ctrl & 0xf8) | 15888c2ecf20Sopenharmony_ci TRF7970A_MODULATOR_DEPTH_ASK10; 15898c2ecf20Sopenharmony_ci break; 15908c2ecf20Sopenharmony_ci default: 15918c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); 15928c2ecf20Sopenharmony_ci return -EINVAL; 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci trf->technology = tech; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci /* Normally we write the ISO_CTRL register in 15988c2ecf20Sopenharmony_ci * trf7970a_tg_config_framing() because the framing can change 15998c2ecf20Sopenharmony_ci * the value written. However, when sending a PSL RES, 16008c2ecf20Sopenharmony_ci * digital_tg_send_psl_res_complete() doesn't call 16018c2ecf20Sopenharmony_ci * trf7970a_tg_config_framing() so we must write the register 16028c2ecf20Sopenharmony_ci * here. 16038c2ecf20Sopenharmony_ci */ 16048c2ecf20Sopenharmony_ci if ((trf->framing == NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED) && 16058c2ecf20Sopenharmony_ci (trf->iso_ctrl_tech != trf->iso_ctrl)) { 16068c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, 16078c2ecf20Sopenharmony_ci trf->iso_ctrl_tech); 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci trf->iso_ctrl = trf->iso_ctrl_tech; 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci return ret; 16138c2ecf20Sopenharmony_ci} 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci/* Since this is a target routine, several of the framing calls are 16168c2ecf20Sopenharmony_ci * made between receiving the request and sending the response so they 16178c2ecf20Sopenharmony_ci * should take effect until after the response is sent. This is accomplished 16188c2ecf20Sopenharmony_ci * by skipping the ISO_CTRL register write here and doing it in the interrupt 16198c2ecf20Sopenharmony_ci * handler. 16208c2ecf20Sopenharmony_ci */ 16218c2ecf20Sopenharmony_cistatic int trf7970a_tg_config_framing(struct trf7970a *trf, int framing) 16228c2ecf20Sopenharmony_ci{ 16238c2ecf20Sopenharmony_ci u8 iso_ctrl = trf->iso_ctrl_tech; 16248c2ecf20Sopenharmony_ci int ret; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "framing: %d\n", framing); 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci switch (framing) { 16298c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP: 16308c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; 16318c2ecf20Sopenharmony_ci iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; 16328c2ecf20Sopenharmony_ci break; 16338c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_STANDARD: 16348c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: 16358c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE: 16368c2ecf20Sopenharmony_ci /* These ones are applied in the interrupt handler */ 16378c2ecf20Sopenharmony_ci iso_ctrl = trf->iso_ctrl; /* Don't write to ISO_CTRL yet */ 16388c2ecf20Sopenharmony_ci break; 16398c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP: 16408c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT; 16418c2ecf20Sopenharmony_ci iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; 16428c2ecf20Sopenharmony_ci break; 16438c2ecf20Sopenharmony_ci case NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED: 16448c2ecf20Sopenharmony_ci trf->tx_cmd = TRF7970A_CMD_TRANSMIT; 16458c2ecf20Sopenharmony_ci iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; 16468c2ecf20Sopenharmony_ci break; 16478c2ecf20Sopenharmony_ci default: 16488c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing); 16498c2ecf20Sopenharmony_ci return -EINVAL; 16508c2ecf20Sopenharmony_ci } 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci trf->framing = framing; 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci if (iso_ctrl != trf->iso_ctrl) { 16558c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 16568c2ecf20Sopenharmony_ci if (ret) 16578c2ecf20Sopenharmony_ci return ret; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci trf->iso_ctrl = iso_ctrl; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 16628c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl); 16638c2ecf20Sopenharmony_ci if (ret) 16648c2ecf20Sopenharmony_ci return ret; 16658c2ecf20Sopenharmony_ci } 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) { 16688c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, 16698c2ecf20Sopenharmony_ci trf->chip_status_ctrl | 16708c2ecf20Sopenharmony_ci TRF7970A_CHIP_STATUS_RF_ON); 16718c2ecf20Sopenharmony_ci if (ret) 16728c2ecf20Sopenharmony_ci return ret; 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON; 16758c2ecf20Sopenharmony_ci } 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci return 0; 16788c2ecf20Sopenharmony_ci} 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_cistatic int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev, int type, 16818c2ecf20Sopenharmony_ci int param) 16828c2ecf20Sopenharmony_ci{ 16838c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 16848c2ecf20Sopenharmony_ci int ret; 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param); 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci trf->is_initiator = false; 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci if ((trf->state == TRF7970A_ST_PWR_OFF) || 16938c2ecf20Sopenharmony_ci (trf->state == TRF7970A_ST_RF_OFF)) { 16948c2ecf20Sopenharmony_ci ret = trf7970a_switch_rf_on(trf); 16958c2ecf20Sopenharmony_ci if (ret) 16968c2ecf20Sopenharmony_ci goto err_unlock; 16978c2ecf20Sopenharmony_ci } 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci switch (type) { 17008c2ecf20Sopenharmony_ci case NFC_DIGITAL_CONFIG_RF_TECH: 17018c2ecf20Sopenharmony_ci ret = trf7970a_tg_config_rf_tech(trf, param); 17028c2ecf20Sopenharmony_ci break; 17038c2ecf20Sopenharmony_ci case NFC_DIGITAL_CONFIG_FRAMING: 17048c2ecf20Sopenharmony_ci ret = trf7970a_tg_config_framing(trf, param); 17058c2ecf20Sopenharmony_ci break; 17068c2ecf20Sopenharmony_ci default: 17078c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Unknown type: %d\n", type); 17088c2ecf20Sopenharmony_ci ret = -EINVAL; 17098c2ecf20Sopenharmony_ci } 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_cierr_unlock: 17128c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 17138c2ecf20Sopenharmony_ci return ret; 17148c2ecf20Sopenharmony_ci} 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_cistatic int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, 17178c2ecf20Sopenharmony_ci nfc_digital_cmd_complete_t cb, void *arg, 17188c2ecf20Sopenharmony_ci bool mode_detect) 17198c2ecf20Sopenharmony_ci{ 17208c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 17218c2ecf20Sopenharmony_ci int ret; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci if ((trf->state != TRF7970A_ST_IDLE) && 17268c2ecf20Sopenharmony_ci (trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) { 17278c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Bogus state: %d\n", __func__, 17288c2ecf20Sopenharmony_ci trf->state); 17298c2ecf20Sopenharmony_ci ret = -EIO; 17308c2ecf20Sopenharmony_ci goto out_err; 17318c2ecf20Sopenharmony_ci } 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci if (trf->aborting) { 17348c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Abort process complete\n"); 17358c2ecf20Sopenharmony_ci trf->aborting = false; 17368c2ecf20Sopenharmony_ci ret = -ECANCELED; 17378c2ecf20Sopenharmony_ci goto out_err; 17388c2ecf20Sopenharmony_ci } 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE, 17418c2ecf20Sopenharmony_ci GFP_KERNEL); 17428c2ecf20Sopenharmony_ci if (!trf->rx_skb) { 17438c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Can't alloc rx_skb\n"); 17448c2ecf20Sopenharmony_ci ret = -ENOMEM; 17458c2ecf20Sopenharmony_ci goto out_err; 17468c2ecf20Sopenharmony_ci } 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_RX_SPECIAL_SETTINGS, 17498c2ecf20Sopenharmony_ci TRF7970A_RX_SPECIAL_SETTINGS_HBT | 17508c2ecf20Sopenharmony_ci TRF7970A_RX_SPECIAL_SETTINGS_M848 | 17518c2ecf20Sopenharmony_ci TRF7970A_RX_SPECIAL_SETTINGS_C424 | 17528c2ecf20Sopenharmony_ci TRF7970A_RX_SPECIAL_SETTINGS_C212); 17538c2ecf20Sopenharmony_ci if (ret) 17548c2ecf20Sopenharmony_ci goto out_err; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL, 17578c2ecf20Sopenharmony_ci trf->io_ctrl | TRF7970A_REG_IO_CTRL_VRS(0x1)); 17588c2ecf20Sopenharmony_ci if (ret) 17598c2ecf20Sopenharmony_ci goto out_err; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_NFC_LOW_FIELD_LEVEL, 17628c2ecf20Sopenharmony_ci TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(0x3)); 17638c2ecf20Sopenharmony_ci if (ret) 17648c2ecf20Sopenharmony_ci goto out_err; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 17678c2ecf20Sopenharmony_ci TRF7970A_NFC_TARGET_LEVEL_RFDET(0x7)); 17688c2ecf20Sopenharmony_ci if (ret) 17698c2ecf20Sopenharmony_ci goto out_err; 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci trf->ddev = ddev; 17728c2ecf20Sopenharmony_ci trf->cb = cb; 17738c2ecf20Sopenharmony_ci trf->cb_arg = arg; 17748c2ecf20Sopenharmony_ci trf->timeout = timeout; 17758c2ecf20Sopenharmony_ci trf->ignore_timeout = false; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX); 17788c2ecf20Sopenharmony_ci if (ret) 17798c2ecf20Sopenharmony_ci goto out_err; 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci trf->state = mode_detect ? TRF7970A_ST_LISTENING_MD : 17828c2ecf20Sopenharmony_ci TRF7970A_ST_LISTENING; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout)); 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ciout_err: 17878c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 17888c2ecf20Sopenharmony_ci return ret; 17898c2ecf20Sopenharmony_ci} 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_cistatic int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, 17928c2ecf20Sopenharmony_ci nfc_digital_cmd_complete_t cb, void *arg) 17938c2ecf20Sopenharmony_ci{ 17948c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n", 17978c2ecf20Sopenharmony_ci trf->state, timeout); 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci return _trf7970a_tg_listen(ddev, timeout, cb, arg, false); 18008c2ecf20Sopenharmony_ci} 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_cistatic int trf7970a_tg_listen_md(struct nfc_digital_dev *ddev, 18038c2ecf20Sopenharmony_ci u16 timeout, nfc_digital_cmd_complete_t cb, 18048c2ecf20Sopenharmony_ci void *arg) 18058c2ecf20Sopenharmony_ci{ 18068c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 18078c2ecf20Sopenharmony_ci int ret; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Listen MD - state: %d, timeout: %d ms\n", 18108c2ecf20Sopenharmony_ci trf->state, timeout); 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, 18138c2ecf20Sopenharmony_ci NFC_DIGITAL_RF_TECH_106A); 18148c2ecf20Sopenharmony_ci if (ret) 18158c2ecf20Sopenharmony_ci return ret; 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, 18188c2ecf20Sopenharmony_ci NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); 18198c2ecf20Sopenharmony_ci if (ret) 18208c2ecf20Sopenharmony_ci return ret; 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci return _trf7970a_tg_listen(ddev, timeout, cb, arg, true); 18238c2ecf20Sopenharmony_ci} 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_cistatic int trf7970a_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech) 18268c2ecf20Sopenharmony_ci{ 18278c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Get RF Tech - state: %d, rf_tech: %d\n", 18308c2ecf20Sopenharmony_ci trf->state, trf->md_rf_tech); 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci *rf_tech = trf->md_rf_tech; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci return 0; 18358c2ecf20Sopenharmony_ci} 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_cistatic void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) 18388c2ecf20Sopenharmony_ci{ 18398c2ecf20Sopenharmony_ci struct trf7970a *trf = nfc_digital_get_drvdata(ddev); 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Abort process initiated\n"); 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci switch (trf->state) { 18468c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_TX_FIFO: 18478c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA: 18488c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: 18498c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_TO_ISSUE_EOF: 18508c2ecf20Sopenharmony_ci trf->aborting = true; 18518c2ecf20Sopenharmony_ci break; 18528c2ecf20Sopenharmony_ci case TRF7970A_ST_LISTENING: 18538c2ecf20Sopenharmony_ci trf->ignore_timeout = !cancel_delayed_work(&trf->timeout_work); 18548c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -ECANCELED); 18558c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Abort process complete\n"); 18568c2ecf20Sopenharmony_ci break; 18578c2ecf20Sopenharmony_ci default: 18588c2ecf20Sopenharmony_ci break; 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 18628c2ecf20Sopenharmony_ci} 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_cistatic struct nfc_digital_ops trf7970a_nfc_ops = { 18658c2ecf20Sopenharmony_ci .in_configure_hw = trf7970a_in_configure_hw, 18668c2ecf20Sopenharmony_ci .in_send_cmd = trf7970a_send_cmd, 18678c2ecf20Sopenharmony_ci .tg_configure_hw = trf7970a_tg_configure_hw, 18688c2ecf20Sopenharmony_ci .tg_send_cmd = trf7970a_send_cmd, 18698c2ecf20Sopenharmony_ci .tg_listen = trf7970a_tg_listen, 18708c2ecf20Sopenharmony_ci .tg_listen_md = trf7970a_tg_listen_md, 18718c2ecf20Sopenharmony_ci .tg_get_rf_tech = trf7970a_tg_get_rf_tech, 18728c2ecf20Sopenharmony_ci .switch_rf = trf7970a_switch_rf, 18738c2ecf20Sopenharmony_ci .abort_cmd = trf7970a_abort_cmd, 18748c2ecf20Sopenharmony_ci}; 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_cistatic int trf7970a_power_up(struct trf7970a *trf) 18778c2ecf20Sopenharmony_ci{ 18788c2ecf20Sopenharmony_ci int ret; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Powering up - state: %d\n", trf->state); 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci if (trf->state != TRF7970A_ST_PWR_OFF) 18838c2ecf20Sopenharmony_ci return 0; 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci ret = regulator_enable(trf->regulator); 18868c2ecf20Sopenharmony_ci if (ret) { 18878c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret); 18888c2ecf20Sopenharmony_ci return ret; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci usleep_range(5000, 6000); 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci if (trf->en2_gpiod && 18948c2ecf20Sopenharmony_ci !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) { 18958c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(trf->en2_gpiod, 1); 18968c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(trf->en_gpiod, 1); 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci usleep_range(20000, 21000); 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_RF_OFF; 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci return 0; 19068c2ecf20Sopenharmony_ci} 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_cistatic int trf7970a_power_down(struct trf7970a *trf) 19098c2ecf20Sopenharmony_ci{ 19108c2ecf20Sopenharmony_ci int ret; 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Powering down - state: %d\n", trf->state); 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci if (trf->state == TRF7970A_ST_PWR_OFF) 19158c2ecf20Sopenharmony_ci return 0; 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci if (trf->state != TRF7970A_ST_RF_OFF) { 19188c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "Can't power down - not RF_OFF state (%d)\n", 19198c2ecf20Sopenharmony_ci trf->state); 19208c2ecf20Sopenharmony_ci return -EBUSY; 19218c2ecf20Sopenharmony_ci } 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(trf->en_gpiod, 0); 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) 19268c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(trf->en2_gpiod, 0); 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci ret = regulator_disable(trf->regulator); 19298c2ecf20Sopenharmony_ci if (ret) 19308c2ecf20Sopenharmony_ci dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__, 19318c2ecf20Sopenharmony_ci ret); 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_PWR_OFF; 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci return ret; 19368c2ecf20Sopenharmony_ci} 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_cistatic int trf7970a_startup(struct trf7970a *trf) 19398c2ecf20Sopenharmony_ci{ 19408c2ecf20Sopenharmony_ci int ret; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci ret = trf7970a_power_up(trf); 19438c2ecf20Sopenharmony_ci if (ret) 19448c2ecf20Sopenharmony_ci return ret; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci pm_runtime_set_active(trf->dev); 19478c2ecf20Sopenharmony_ci pm_runtime_enable(trf->dev); 19488c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(trf->dev); 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci return 0; 19518c2ecf20Sopenharmony_ci} 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_cistatic void trf7970a_shutdown(struct trf7970a *trf) 19548c2ecf20Sopenharmony_ci{ 19558c2ecf20Sopenharmony_ci switch (trf->state) { 19568c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_TX_FIFO: 19578c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA: 19588c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: 19598c2ecf20Sopenharmony_ci case TRF7970A_ST_WAIT_TO_ISSUE_EOF: 19608c2ecf20Sopenharmony_ci case TRF7970A_ST_LISTENING: 19618c2ecf20Sopenharmony_ci trf7970a_send_err_upstream(trf, -ECANCELED); 19628c2ecf20Sopenharmony_ci fallthrough; 19638c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE: 19648c2ecf20Sopenharmony_ci case TRF7970A_ST_IDLE_RX_BLOCKED: 19658c2ecf20Sopenharmony_ci trf7970a_switch_rf_off(trf); 19668c2ecf20Sopenharmony_ci break; 19678c2ecf20Sopenharmony_ci default: 19688c2ecf20Sopenharmony_ci break; 19698c2ecf20Sopenharmony_ci } 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci pm_runtime_disable(trf->dev); 19728c2ecf20Sopenharmony_ci pm_runtime_set_suspended(trf->dev); 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci trf7970a_power_down(trf); 19758c2ecf20Sopenharmony_ci} 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_cistatic int trf7970a_get_autosuspend_delay(struct device_node *np) 19788c2ecf20Sopenharmony_ci{ 19798c2ecf20Sopenharmony_ci int autosuspend_delay, ret; 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "autosuspend-delay", &autosuspend_delay); 19828c2ecf20Sopenharmony_ci if (ret) 19838c2ecf20Sopenharmony_ci autosuspend_delay = TRF7970A_AUTOSUSPEND_DELAY; 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci return autosuspend_delay; 19868c2ecf20Sopenharmony_ci} 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_cistatic int trf7970a_probe(struct spi_device *spi) 19898c2ecf20Sopenharmony_ci{ 19908c2ecf20Sopenharmony_ci struct device_node *np = spi->dev.of_node; 19918c2ecf20Sopenharmony_ci struct trf7970a *trf; 19928c2ecf20Sopenharmony_ci int uvolts, autosuspend_delay, ret; 19938c2ecf20Sopenharmony_ci u32 clk_freq = TRF7970A_13MHZ_CLOCK_FREQUENCY; 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci if (!np) { 19968c2ecf20Sopenharmony_ci dev_err(&spi->dev, "No Device Tree entry\n"); 19978c2ecf20Sopenharmony_ci return -EINVAL; 19988c2ecf20Sopenharmony_ci } 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci trf = devm_kzalloc(&spi->dev, sizeof(*trf), GFP_KERNEL); 20018c2ecf20Sopenharmony_ci if (!trf) 20028c2ecf20Sopenharmony_ci return -ENOMEM; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci trf->state = TRF7970A_ST_PWR_OFF; 20058c2ecf20Sopenharmony_ci trf->dev = &spi->dev; 20068c2ecf20Sopenharmony_ci trf->spi = spi; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci spi->mode = SPI_MODE_1; 20098c2ecf20Sopenharmony_ci spi->bits_per_word = 8; 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci ret = spi_setup(spi); 20128c2ecf20Sopenharmony_ci if (ret < 0) { 20138c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't set up SPI Communication\n"); 20148c2ecf20Sopenharmony_ci return ret; 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci if (of_property_read_bool(np, "irq-status-read-quirk")) 20188c2ecf20Sopenharmony_ci trf->quirks |= TRF7970A_QUIRK_IRQ_STATUS_READ; 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci /* There are two enable pins - only EN must be present in the DT */ 20218c2ecf20Sopenharmony_ci trf->en_gpiod = devm_gpiod_get_index(trf->dev, "ti,enable", 0, 20228c2ecf20Sopenharmony_ci GPIOD_OUT_LOW); 20238c2ecf20Sopenharmony_ci if (IS_ERR(trf->en_gpiod)) { 20248c2ecf20Sopenharmony_ci dev_err(trf->dev, "No EN GPIO property\n"); 20258c2ecf20Sopenharmony_ci return PTR_ERR(trf->en_gpiod); 20268c2ecf20Sopenharmony_ci } 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci trf->en2_gpiod = devm_gpiod_get_index_optional(trf->dev, "ti,enable", 1, 20298c2ecf20Sopenharmony_ci GPIOD_OUT_LOW); 20308c2ecf20Sopenharmony_ci if (!trf->en2_gpiod) { 20318c2ecf20Sopenharmony_ci dev_info(trf->dev, "No EN2 GPIO property\n"); 20328c2ecf20Sopenharmony_ci } else if (IS_ERR(trf->en2_gpiod)) { 20338c2ecf20Sopenharmony_ci dev_err(trf->dev, "Error getting EN2 GPIO property: %ld\n", 20348c2ecf20Sopenharmony_ci PTR_ERR(trf->en2_gpiod)); 20358c2ecf20Sopenharmony_ci return PTR_ERR(trf->en2_gpiod); 20368c2ecf20Sopenharmony_ci } else if (of_property_read_bool(np, "en2-rf-quirk")) { 20378c2ecf20Sopenharmony_ci trf->quirks |= TRF7970A_QUIRK_EN2_MUST_STAY_LOW; 20388c2ecf20Sopenharmony_ci } 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci of_property_read_u32(np, "clock-frequency", &clk_freq); 20418c2ecf20Sopenharmony_ci if ((clk_freq != TRF7970A_27MHZ_CLOCK_FREQUENCY) && 20428c2ecf20Sopenharmony_ci (clk_freq != TRF7970A_13MHZ_CLOCK_FREQUENCY)) { 20438c2ecf20Sopenharmony_ci dev_err(trf->dev, 20448c2ecf20Sopenharmony_ci "clock-frequency (%u Hz) unsupported\n", clk_freq); 20458c2ecf20Sopenharmony_ci return -EINVAL; 20468c2ecf20Sopenharmony_ci } 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_ci if (clk_freq == TRF7970A_27MHZ_CLOCK_FREQUENCY) { 20498c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_27MHZ; 20508c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "trf7970a configured for 27MHz crystal\n"); 20518c2ecf20Sopenharmony_ci } else { 20528c2ecf20Sopenharmony_ci trf->modulator_sys_clk_ctrl = 0; 20538c2ecf20Sopenharmony_ci } 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(trf->dev, spi->irq, NULL, 20568c2ecf20Sopenharmony_ci trf7970a_irq, 20578c2ecf20Sopenharmony_ci IRQF_TRIGGER_RISING | IRQF_ONESHOT, 20588c2ecf20Sopenharmony_ci "trf7970a", trf); 20598c2ecf20Sopenharmony_ci if (ret) { 20608c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't request IRQ#%d: %d\n", spi->irq, ret); 20618c2ecf20Sopenharmony_ci return ret; 20628c2ecf20Sopenharmony_ci } 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci mutex_init(&trf->lock); 20658c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler); 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci trf->regulator = devm_regulator_get(&spi->dev, "vin"); 20688c2ecf20Sopenharmony_ci if (IS_ERR(trf->regulator)) { 20698c2ecf20Sopenharmony_ci ret = PTR_ERR(trf->regulator); 20708c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret); 20718c2ecf20Sopenharmony_ci goto err_destroy_lock; 20728c2ecf20Sopenharmony_ci } 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci ret = regulator_enable(trf->regulator); 20758c2ecf20Sopenharmony_ci if (ret) { 20768c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't enable VIN: %d\n", ret); 20778c2ecf20Sopenharmony_ci goto err_destroy_lock; 20788c2ecf20Sopenharmony_ci } 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci uvolts = regulator_get_voltage(trf->regulator); 20818c2ecf20Sopenharmony_ci if (uvolts > 4000000) 20828c2ecf20Sopenharmony_ci trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci trf->regulator = devm_regulator_get(&spi->dev, "vdd-io"); 20858c2ecf20Sopenharmony_ci if (IS_ERR(trf->regulator)) { 20868c2ecf20Sopenharmony_ci ret = PTR_ERR(trf->regulator); 20878c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret); 20888c2ecf20Sopenharmony_ci goto err_destroy_lock; 20898c2ecf20Sopenharmony_ci } 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci ret = regulator_enable(trf->regulator); 20928c2ecf20Sopenharmony_ci if (ret) { 20938c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret); 20948c2ecf20Sopenharmony_ci goto err_destroy_lock; 20958c2ecf20Sopenharmony_ci } 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci if (regulator_get_voltage(trf->regulator) == 1800000) { 20988c2ecf20Sopenharmony_ci trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW; 20998c2ecf20Sopenharmony_ci dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n"); 21008c2ecf20Sopenharmony_ci } 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, 21038c2ecf20Sopenharmony_ci TRF7970A_SUPPORTED_PROTOCOLS, 21048c2ecf20Sopenharmony_ci NFC_DIGITAL_DRV_CAPS_IN_CRC | 21058c2ecf20Sopenharmony_ci NFC_DIGITAL_DRV_CAPS_TG_CRC, 0, 21068c2ecf20Sopenharmony_ci 0); 21078c2ecf20Sopenharmony_ci if (!trf->ddev) { 21088c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't allocate NFC digital device\n"); 21098c2ecf20Sopenharmony_ci ret = -ENOMEM; 21108c2ecf20Sopenharmony_ci goto err_disable_regulator; 21118c2ecf20Sopenharmony_ci } 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ci nfc_digital_set_parent_dev(trf->ddev, trf->dev); 21148c2ecf20Sopenharmony_ci nfc_digital_set_drvdata(trf->ddev, trf); 21158c2ecf20Sopenharmony_ci spi_set_drvdata(spi, trf); 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_ci autosuspend_delay = trf7970a_get_autosuspend_delay(np); 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(trf->dev, autosuspend_delay); 21208c2ecf20Sopenharmony_ci pm_runtime_use_autosuspend(trf->dev); 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci ret = trf7970a_startup(trf); 21238c2ecf20Sopenharmony_ci if (ret) 21248c2ecf20Sopenharmony_ci goto err_free_ddev; 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci ret = nfc_digital_register_device(trf->ddev); 21278c2ecf20Sopenharmony_ci if (ret) { 21288c2ecf20Sopenharmony_ci dev_err(trf->dev, "Can't register NFC digital device: %d\n", 21298c2ecf20Sopenharmony_ci ret); 21308c2ecf20Sopenharmony_ci goto err_shutdown; 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci return 0; 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_cierr_shutdown: 21368c2ecf20Sopenharmony_ci trf7970a_shutdown(trf); 21378c2ecf20Sopenharmony_cierr_free_ddev: 21388c2ecf20Sopenharmony_ci nfc_digital_free_device(trf->ddev); 21398c2ecf20Sopenharmony_cierr_disable_regulator: 21408c2ecf20Sopenharmony_ci regulator_disable(trf->regulator); 21418c2ecf20Sopenharmony_cierr_destroy_lock: 21428c2ecf20Sopenharmony_ci mutex_destroy(&trf->lock); 21438c2ecf20Sopenharmony_ci return ret; 21448c2ecf20Sopenharmony_ci} 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_cistatic int trf7970a_remove(struct spi_device *spi) 21478c2ecf20Sopenharmony_ci{ 21488c2ecf20Sopenharmony_ci struct trf7970a *trf = spi_get_drvdata(spi); 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci trf7970a_shutdown(trf); 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci nfc_digital_unregister_device(trf->ddev); 21578c2ecf20Sopenharmony_ci nfc_digital_free_device(trf->ddev); 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci regulator_disable(trf->regulator); 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci mutex_destroy(&trf->lock); 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci return 0; 21648c2ecf20Sopenharmony_ci} 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 21678c2ecf20Sopenharmony_cistatic int trf7970a_suspend(struct device *dev) 21688c2ecf20Sopenharmony_ci{ 21698c2ecf20Sopenharmony_ci struct spi_device *spi = to_spi_device(dev); 21708c2ecf20Sopenharmony_ci struct trf7970a *trf = spi_get_drvdata(spi); 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci dev_dbg(dev, "Suspend\n"); 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci trf7970a_shutdown(trf); 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci return 0; 21818c2ecf20Sopenharmony_ci} 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_cistatic int trf7970a_resume(struct device *dev) 21848c2ecf20Sopenharmony_ci{ 21858c2ecf20Sopenharmony_ci struct spi_device *spi = to_spi_device(dev); 21868c2ecf20Sopenharmony_ci struct trf7970a *trf = spi_get_drvdata(spi); 21878c2ecf20Sopenharmony_ci int ret; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci dev_dbg(dev, "Resume\n"); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci ret = trf7970a_startup(trf); 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci return ret; 21988c2ecf20Sopenharmony_ci} 21998c2ecf20Sopenharmony_ci#endif 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 22028c2ecf20Sopenharmony_cistatic int trf7970a_pm_runtime_suspend(struct device *dev) 22038c2ecf20Sopenharmony_ci{ 22048c2ecf20Sopenharmony_ci struct spi_device *spi = to_spi_device(dev); 22058c2ecf20Sopenharmony_ci struct trf7970a *trf = spi_get_drvdata(spi); 22068c2ecf20Sopenharmony_ci int ret; 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci dev_dbg(dev, "Runtime suspend\n"); 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci mutex_lock(&trf->lock); 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci ret = trf7970a_power_down(trf); 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci mutex_unlock(&trf->lock); 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci return ret; 22178c2ecf20Sopenharmony_ci} 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_cistatic int trf7970a_pm_runtime_resume(struct device *dev) 22208c2ecf20Sopenharmony_ci{ 22218c2ecf20Sopenharmony_ci struct spi_device *spi = to_spi_device(dev); 22228c2ecf20Sopenharmony_ci struct trf7970a *trf = spi_get_drvdata(spi); 22238c2ecf20Sopenharmony_ci int ret; 22248c2ecf20Sopenharmony_ci 22258c2ecf20Sopenharmony_ci dev_dbg(dev, "Runtime resume\n"); 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci ret = trf7970a_power_up(trf); 22288c2ecf20Sopenharmony_ci if (!ret) 22298c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dev); 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci return ret; 22328c2ecf20Sopenharmony_ci} 22338c2ecf20Sopenharmony_ci#endif 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_cistatic const struct dev_pm_ops trf7970a_pm_ops = { 22368c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(trf7970a_suspend, trf7970a_resume) 22378c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(trf7970a_pm_runtime_suspend, 22388c2ecf20Sopenharmony_ci trf7970a_pm_runtime_resume, NULL) 22398c2ecf20Sopenharmony_ci}; 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_cistatic const struct of_device_id trf7970a_of_match[] = { 22428c2ecf20Sopenharmony_ci {.compatible = "ti,trf7970a",}, 22438c2ecf20Sopenharmony_ci {}, 22448c2ecf20Sopenharmony_ci}; 22458c2ecf20Sopenharmony_ci 22468c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, trf7970a_of_match); 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_cistatic const struct spi_device_id trf7970a_id_table[] = { 22498c2ecf20Sopenharmony_ci {"trf7970a", 0}, 22508c2ecf20Sopenharmony_ci {} 22518c2ecf20Sopenharmony_ci}; 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(spi, trf7970a_id_table); 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_cistatic struct spi_driver trf7970a_spi_driver = { 22568c2ecf20Sopenharmony_ci .probe = trf7970a_probe, 22578c2ecf20Sopenharmony_ci .remove = trf7970a_remove, 22588c2ecf20Sopenharmony_ci .id_table = trf7970a_id_table, 22598c2ecf20Sopenharmony_ci .driver = { 22608c2ecf20Sopenharmony_ci .name = "trf7970a", 22618c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(trf7970a_of_match), 22628c2ecf20Sopenharmony_ci .pm = &trf7970a_pm_ops, 22638c2ecf20Sopenharmony_ci }, 22648c2ecf20Sopenharmony_ci}; 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_cimodule_spi_driver(trf7970a_spi_driver); 22678c2ecf20Sopenharmony_ci 22688c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>"); 22698c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 22708c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("TI trf7970a RFID/NFC Transceiver Driver"); 2271