From 3bd14233aa0733fbc6c3f75ec928f1a393522644 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 7 Aug 2014 17:41:41 -0700 Subject: NFC: trf7970a: Add VIN voltage override support The trf7970a driver uses the voltage from the power/regulator subsystem to determine what the voltage on the VIN pin is. Normally, this is the right thing to do but sometimes the board that the trf7970a is on may change the voltage. This is the case for the trf7970atb board from Texas Instruments where it boosts the VIN voltage from 3.3V to 5V (see http://www.ti.com/tool/trf7970atb). To handle this, add support for the 'vin-voltage-override' device tree property which overrides the voltage value given by the regulator subsystem. When the DT property is not present, the value from the regulator subsystem is used. The value of 'vin-voltage-override' is in uVolts. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 3b78b031e617..5355d0e4c045 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1251,6 +1251,12 @@ static int trf7970a_get_autosuspend_delay(struct device_node *np) return autosuspend_delay; } +static int trf7970a_get_vin_voltage_override(struct device_node *np, + u32 *vin_uvolts) +{ + return of_property_read_u32(np, "vin-voltage-override", vin_uvolts); +} + static int trf7970a_probe(struct spi_device *spi) { struct device_node *np = spi->dev.of_node; @@ -1326,7 +1332,9 @@ static int trf7970a_probe(struct spi_device *spi) goto err_destroy_lock; } - uvolts = regulator_get_voltage(trf->regulator); + ret = trf7970a_get_vin_voltage_override(np, &uvolts); + if (ret) + uvolts = regulator_get_voltage(trf->regulator); if (uvolts > 4000000) trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; -- cgit v1.2.3 From 772079eb77587e0242752fa67685a8132d899f79 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 7 Aug 2014 17:41:43 -0700 Subject: NFC: trf7970a: Move IRQ Status Read quirk to device tree The quirk indicating whether the trf7970a has the "IRQ Status Read" erratum or not is currently implemented using the 'driver_data' member of the 'spi_device_id' structure. That requires the driver to be modified to turn the quirk off when a version of the trf7970a that doesn't have the erratum is being used. To fix that, create a new device tree property called 'irq-status-read-quirk' that indicates that the trf7970a being used has the erratum. While at it, rename 'TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA' to 'TRF7970A_QUIRK_IRQ_STATUS_READ' to make it less of an eyesore. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 5355d0e4c045..3cc7001d7d2f 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -132,7 +132,7 @@ /* Erratum: When reading IRQ Status register on trf7970a, we must issue a * read continuous command for IRQ Status and Collision Position registers. */ -#define TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA BIT(0) +#define TRF7970A_QUIRK_IRQ_STATUS_READ BIT(0) /* Direct commands */ #define TRF7970A_CMD_IDLE 0x00 @@ -424,7 +424,7 @@ static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status) addr = TRF7970A_IRQ_STATUS | TRF7970A_CMD_BIT_RW; - if (trf->quirks & TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA) { + if (trf->quirks & TRF7970A_QUIRK_IRQ_STATUS_READ) { addr |= TRF7970A_CMD_BIT_CONTINUOUS; ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2); } else { @@ -1260,7 +1260,6 @@ static int trf7970a_get_vin_voltage_override(struct device_node *np, static int trf7970a_probe(struct spi_device *spi) { struct device_node *np = spi->dev.of_node; - const struct spi_device_id *id = spi_get_device_id(spi); struct trf7970a *trf; int uvolts, autosuspend_delay, ret; @@ -1276,11 +1275,13 @@ static int trf7970a_probe(struct spi_device *spi) trf->state = TRF7970A_ST_OFF; trf->dev = &spi->dev; trf->spi = spi; - trf->quirks = id->driver_data; spi->mode = SPI_MODE_1; spi->bits_per_word = 8; + if (of_property_read_bool(np, "irq-status-read-quirk")) + trf->quirks |= TRF7970A_QUIRK_IRQ_STATUS_READ; + /* There are two enable pins - both must be present */ trf->en_gpio = of_get_named_gpio(np, "ti,enable-gpios", 0); if (!gpio_is_valid(trf->en_gpio)) { @@ -1478,7 +1479,7 @@ static const struct dev_pm_ops trf7970a_pm_ops = { }; static const struct spi_device_id trf7970a_id_table[] = { - { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA }, + { "trf7970a", 0 }, { } }; MODULE_DEVICE_TABLE(spi, trf7970a_id_table); -- cgit v1.2.3 From 95064bd95a822659f4a606b485aba5009d70fc88 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 7 Aug 2014 17:41:45 -0700 Subject: NFC: trf7970a: Add quirk to keep EN2 low A bug has been discovered in the trf7970a where it will generate an RF field even in passive target mode when EN2 is asserted. To work around this, add support for the 'en2-rf-quirk' device tree property which indicates that EN2 must remain low. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 3cc7001d7d2f..870867d645e0 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -36,7 +36,13 @@ * The trf7970a is very timing sensitive and the VIN, EN2, and EN * pins must asserted in that order and with specific delays in between. * The delays used in the driver were provided by TI and have been - * confirmed to work with this driver. + * confirmed to work with this driver. There is a bug with the current + * version of the trf7970a that requires that EN2 remain low no matter + * what. If it goes high, it will generate an RF field even when in + * passive target mode. TI has indicated that the chip will work okay + * when EN2 is left low. The 'en2-rf-quirk' device tree property + * indicates that trf7970a currently being used has the erratum and + * that EN2 must be kept low. * * Timeouts are implemented using the delayed workqueue kernel facility. * Timeouts are required so things don't hang when there is no response @@ -133,6 +139,7 @@ * read continuous command for IRQ Status and Collision Position registers. */ #define TRF7970A_QUIRK_IRQ_STATUS_READ BIT(0) +#define TRF7970A_QUIRK_EN2_MUST_STAY_LOW BIT(1) /* Direct commands */ #define TRF7970A_CMD_IDLE 0x00 @@ -1309,6 +1316,9 @@ static int trf7970a_probe(struct spi_device *spi) return ret; } + if (of_property_read_bool(np, "en2-rf-quirk")) + trf->quirks |= TRF7970A_QUIRK_EN2_MUST_STAY_LOW; + ret = devm_request_threaded_irq(trf->dev, spi->irq, NULL, trf7970a_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "trf7970a", trf); @@ -1455,8 +1465,11 @@ static int trf7970a_pm_runtime_resume(struct device *dev) usleep_range(5000, 6000); - gpio_set_value(trf->en2_gpio, 1); - usleep_range(1000, 2000); + if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) { + gpio_set_value(trf->en2_gpio, 1); + usleep_range(1000, 2000); + } + gpio_set_value(trf->en_gpio, 1); usleep_range(20000, 21000); -- cgit v1.2.3 From f23b73526b82ca2ef333362e704a51d817c1ffc1 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 7 Aug 2014 17:41:47 -0700 Subject: NFC: trf7970a: Make gpio labels more readable Make the labels for the two gpio enable lines more user friendly by prefixing them with the driver name. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 870867d645e0..3e950ddaaf77 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1297,7 +1297,7 @@ static int trf7970a_probe(struct spi_device *spi) } ret = devm_gpio_request_one(trf->dev, trf->en_gpio, - GPIOF_DIR_OUT | GPIOF_INIT_LOW, "EN"); + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "trf7970a EN"); if (ret) { dev_err(trf->dev, "Can't request EN GPIO: %d\n", ret); return ret; @@ -1310,7 +1310,7 @@ static int trf7970a_probe(struct spi_device *spi) } ret = devm_gpio_request_one(trf->dev, trf->en2_gpio, - GPIOF_DIR_OUT | GPIOF_INIT_LOW, "EN2"); + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "trf7970a EN2"); if (ret) { dev_err(trf->dev, "Can't request EN2 GPIO: %d\n", ret); return ret; -- cgit v1.2.3 From d3a6d33a7f72fa4d3bb0224da0839a5ca871d7a4 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:15 -0700 Subject: NFC: trf7970a: Remove incorrect of_node_put() call of_property_read_u32() does not take a reference to the specified OF node so don't call of_node_put() in trf7970a_get_autosuspend_delay(). Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 3e950ddaaf77..4387b55f9c70 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1253,8 +1253,6 @@ static int trf7970a_get_autosuspend_delay(struct device_node *np) if (ret) autosuspend_delay = TRF7970A_AUTOSUSPEND_DELAY; - of_node_put(np); - return autosuspend_delay; } -- cgit v1.2.3 From cc8d7158644c439d946bfc65778a507b6f12b10d Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:16 -0700 Subject: NFC: trf7970a: Remove trf7970a_tg_listen_mdaa() Currently, the digital layer 'tg_listen_mdaa' hook is not used and it isn't necessary to have a stub routine so remove it. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 4387b55f9c70..509acac26afd 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1201,17 +1201,6 @@ static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, return -EINVAL; } -static int trf7970a_tg_listen_mdaa(struct nfc_digital_dev *ddev, - struct digital_tg_mdaa_params *mdaa_params, - u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) -{ - struct trf7970a *trf = nfc_digital_get_drvdata(ddev); - - dev_dbg(trf->dev, "Unsupported interface\n"); - - return -EINVAL; -} - static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); @@ -1240,7 +1229,6 @@ static struct nfc_digital_ops trf7970a_nfc_ops = { .tg_configure_hw = trf7970a_tg_configure_hw, .tg_send_cmd = trf7970a_tg_send_cmd, .tg_listen = trf7970a_tg_listen, - .tg_listen_mdaa = trf7970a_tg_listen_mdaa, .switch_rf = trf7970a_switch_rf, .abort_cmd = trf7970a_abort_cmd, }; -- cgit v1.2.3 From 24707296c762d1828c4a51aa1872dc275dc3fccc Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:17 -0700 Subject: NFC: trf7970a: Call spi_setup() to configure SPI communication Call spi_setup() to configure SPI communication with the trf7970a. This will ensure that the correct SPI parameters are used. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 509acac26afd..159b0a3f965b 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1272,6 +1272,12 @@ static int trf7970a_probe(struct spi_device *spi) spi->mode = SPI_MODE_1; spi->bits_per_word = 8; + ret = spi_setup(spi); + if (ret < 0) { + dev_err(trf->dev, "Can't set up SPI Communication\n"); + return ret; + } + if (of_property_read_bool(np, "irq-status-read-quirk")) trf->quirks |= TRF7970A_QUIRK_IRQ_STATUS_READ; -- cgit v1.2.3 From 3e7f335689ebfa0a68814dfe9f0588076fb9ad01 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:18 -0700 Subject: NFC: trf7970a: Use spi_sync() instead of spi_write_then_read() To more efficiently handle long continuous reads, use spi_sync() instead of spi_write_then_read(). Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 159b0a3f965b..badd2c7ffa92 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -393,15 +393,28 @@ static int trf7970a_read(struct trf7970a *trf, u8 reg, u8 *val) return ret; } -static int trf7970a_read_cont(struct trf7970a *trf, u8 reg, - u8 *buf, size_t len) +static int trf7970a_read_cont(struct trf7970a *trf, u8 reg, u8 *buf, size_t len) { u8 addr = reg | TRF7970A_CMD_BIT_RW | TRF7970A_CMD_BIT_CONTINUOUS; + struct spi_transfer t[2]; + struct spi_message m; int ret; dev_dbg(trf->dev, "read_cont(0x%x, %zd)\n", addr, len); - ret = spi_write_then_read(trf->spi, &addr, 1, buf, len); + spi_message_init(&m); + + memset(&t, 0, sizeof(t)); + + t[0].tx_buf = &addr; + t[0].len = sizeof(addr); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + ret = spi_sync(trf->spi, &m); if (ret) dev_err(trf->dev, "%s - addr: 0x%x, ret: %d\n", __func__, addr, ret); -- cgit v1.2.3 From 4542e8345af6076c87d036c7bd3f9dfa30768b1e Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:19 -0700 Subject: NFC: trf7970a: Ignore Overflow bit in FIFO Status Register The Overflow bit in the 'FIFO Status Register' has proven to be untrustworthy so ignore it. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index badd2c7ffa92..ac3db9d9eeca 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -561,12 +561,7 @@ static void trf7970a_fill_fifo(struct trf7970a *trf) dev_dbg(trf->dev, "Filling FIFO - fifo_bytes: 0x%x\n", fifo_bytes); - if (fifo_bytes & TRF7970A_FIFO_STATUS_OVERFLOW) { - dev_err(trf->dev, "%s - fifo overflow: 0x%x\n", __func__, - fifo_bytes); - trf7970a_send_err_upstream(trf, -EIO); - return; - } + fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; /* Calculate how much more data can be written to the fifo */ len = TRF7970A_FIFO_SIZE - fifo_bytes; @@ -596,16 +591,11 @@ static void trf7970a_drain_fifo(struct trf7970a *trf, u8 status) dev_dbg(trf->dev, "Draining FIFO - fifo_bytes: 0x%x\n", fifo_bytes); + fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; + if (!fifo_bytes) goto no_rx_data; - if (fifo_bytes & TRF7970A_FIFO_STATUS_OVERFLOW) { - dev_err(trf->dev, "%s - fifo overflow: 0x%x\n", __func__, - fifo_bytes); - trf7970a_send_err_upstream(trf, -EIO); - return; - } - if (fifo_bytes > skb_tailroom(skb)) { skb = skb_copy_expand(skb, skb_headroom(skb), max_t(int, fifo_bytes, -- cgit v1.2.3 From 1568bfef18a9150d83b0f91aa254cef7ebead4cd Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:20 -0700 Subject: NFC: trf7970a: FIFO Size is really 127 bytes Despite what the manual says, the FIFO size on the trf7970a is really 127 bytes so make the code respect that. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index ac3db9d9eeca..46a075dea67c 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -125,7 +125,7 @@ #define TRF7970A_RX_SKB_ALLOC_SIZE 256 -#define TRF7970A_FIFO_SIZE 128 +#define TRF7970A_FIFO_SIZE 127 /* TX length is 3 nibbles long ==> 4KB - 1 bytes max */ #define TRF7970A_TX_MAX (4096 - 1) -- cgit v1.2.3 From 17b2151733ecdc96ee4fecdf5fae973b8cb0fea7 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:21 -0700 Subject: NFC: trf7970a: Remove unnecessary sleep There is no need to sleep for 1-2 ms before transmitting a new command. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 46a075dea67c..4709bea8deb2 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1160,8 +1160,6 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, len = min_t(int, skb->len, TRF7970A_FIFO_SIZE); - usleep_range(1000, 2000); - ret = trf7970a_transmit(trf, skb, len); if (ret) { kfree_skb(trf->rx_skb); -- cgit v1.2.3 From 6c08df422ede7db94776b8099a5f43597629234c Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:22 -0700 Subject: NFC: trf7970a: Disable SYS_CLK Output Currently, support for providing the external SYS_CLK signal on pin 27 is not supported so turn it off by writing to the 'Modulator and SYS_CLK Control' register immediately after reset. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 4709bea8deb2..9c0549d4f276 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -775,6 +775,12 @@ static int trf7970a_init(struct trf7970a *trf) if (ret) goto err_out; + ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 0); + if (ret) + goto err_out; + + trf->modulator_sys_clk_ctrl = 0; + /* Must clear NFC Target Detection Level reg due to erratum */ ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); if (ret) -- cgit v1.2.3 From a08e54549e743ea3704da939f92caf3eaa8471d3 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:23 -0700 Subject: NFC: trf7970a: Initialize when enabling RF Currently, the trf7970a is reset & initialized only when the pm_runtime resume hook is called. Instead, initialize it every time the RF is enabled to ensure that the trf7970a is quiesced and in a known state before being set up for another RF technology. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 9c0549d4f276..ce9686c44350 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -823,10 +823,18 @@ static void trf7970a_switch_rf_off(struct trf7970a *trf) static void trf7970a_switch_rf_on(struct trf7970a *trf) { + int ret; + dev_dbg(trf->dev, "Switching rf on\n"); pm_runtime_get_sync(trf->dev); + ret = trf7970a_init(trf); + if (ret) { + dev_err(trf->dev, "%s - Can't initialize: %d\n", __func__, ret); + return; + } + trf->state = TRF7970A_ST_IDLE; } @@ -1473,12 +1481,6 @@ static int trf7970a_pm_runtime_resume(struct device *dev) usleep_range(20000, 21000); - ret = trf7970a_init(trf); - if (ret) { - dev_err(dev, "%s - Can't initialize: %d\n", __func__, ret); - return ret; - } - pm_runtime_mark_last_busy(dev); return 0; -- cgit v1.2.3 From 4e64eff837fb682dfb2a1188fb036d75ec57375c Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:24 -0700 Subject: NFC: trf7970a: Add RF technology specific guard times When turning on the RF field, the driver must wait an RF-technology-specific amount of time (known as the guard time) before modulating the field. Currently, the driver waits 5 ms but that is too short for NFCF and too long for ISO/IEC 15693. Fix this by determining the guard time when the RF technology is set and delaying that amount of time when turning on the RF field. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index ce9686c44350..22485e703849 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -134,6 +134,12 @@ #define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3 #define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20 +/* Guard times for various RF technologies (in us) */ +#define TRF7970A_GUARD_TIME_NFCA 5000 +#define TRF7970A_GUARD_TIME_NFCB 5000 +#define TRF7970A_GUARD_TIME_NFCF 20000 +#define TRF7970A_GUARD_TIME_15693 1000 + /* Quirks */ /* Erratum: When reading IRQ Status register on trf7970a, we must issue a * read continuous command for IRQ Status and Collision Position registers. @@ -351,6 +357,7 @@ struct trf7970a { u8 iso_ctrl_tech; u8 modulator_sys_clk_ctrl; u8 special_fcn_reg1; + unsigned int guard_time; int technology; int framing; u8 tx_cmd; @@ -887,22 +894,27 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) case NFC_DIGITAL_RF_TECH_106A: trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443A_106; trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; + trf->guard_time = TRF7970A_GUARD_TIME_NFCA; break; case NFC_DIGITAL_RF_TECH_106B: trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443B_106; trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; + trf->guard_time = TRF7970A_GUARD_TIME_NFCB; break; case NFC_DIGITAL_RF_TECH_212F: trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_212; trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; + trf->guard_time = TRF7970A_GUARD_TIME_NFCF; break; case NFC_DIGITAL_RF_TECH_424F: trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_FELICA_424; trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; + trf->guard_time = TRF7970A_GUARD_TIME_NFCF; break; case NFC_DIGITAL_RF_TECH_ISO15693: trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; + trf->guard_time = TRF7970A_GUARD_TIME_15693; break; default: dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); @@ -971,7 +983,7 @@ static int trf7970a_config_framing(struct trf7970a *trf, int framing) trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON; - usleep_range(5000, 6000); + usleep_range(trf->guard_time, trf->guard_time + 1000); } return 0; -- cgit v1.2.3 From 38b4eb1f7fa87079a5a40f5d2ec4b5c0c7f14a4b Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:25 -0700 Subject: NFC: trf7970a: Recalculate driver timeout values Some of the timeout values used in the driver are not long enough to handle worst-case scenarios so they need to be recalculated. The time to wait for the FIFO to drain past the low-watermark is now 20 ms because it can take around 14.35 ms to send 95 bytes (127 bytes in full FIFO minus 32 bytes where the low-watermark interrupt will fire). 95 bytes will take around 14.35 ms at 6.62 kbps (the lowest supported bit rate used by ISO/IEC 15693) so 20 ms should be a safe value. The time to wait before issuing an EOF to complete an ISO/IEC 15693 write or lock command is 40 ms-- 20 ms to drain the FIFO and another 20 ms to ensure the wait is long enough before sending an EOF. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 22485e703849..b67946c18b40 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -83,6 +83,13 @@ * been received and there isn't an error). The delay is 20 ms since delays * of ~16 ms have been observed during testing. * + * When transmitting a frame larger than the FIFO size (127 bytes), the + * driver will wait 20 ms for the FIFO to drain past the low-watermark + * and generate an interrupt. The low-watermark set to 32 bytes so the + * interrupt should fire after 127 - 32 = 95 bytes have been sent. At + * the lowest possible bit rate (6.62 kbps for 15693), it will take up + * to ~14.35 ms so 20 ms is used for the timeout. + * * Type 2 write and sector select commands respond with a 4-bit ACK or NACK. * Having only 4 bits in the FIFO won't normally generate an interrupt so * driver enables the '4_bit_RX' bit of the Special Functions register 1 @@ -105,7 +112,9 @@ * Note under Table 1-1 in section 1.6 of * http://www.ti.com/lit/ug/scbu011/scbu011.pdf, that wait should be at least * 10 ms for TI Tag-it HF-I tags; however testing has shown that is not long - * enough. For this reason, the driver waits 20 ms which seems to work + * enough so 20 ms is used. So the timer is set to 40 ms - 20 ms to drain + * up to 127 bytes in the FIFO at the lowest bit rate plus another 20 ms to + * ensure the wait is long enough before sending the EOF. This seems to work * reliably. */ @@ -131,8 +140,8 @@ #define TRF7970A_TX_MAX (4096 - 1) #define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 20 -#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3 -#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20 +#define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 20 +#define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 40 /* Guard times for various RF technologies (in us) */ #define TRF7970A_GUARD_TIME_NFCA 5000 -- cgit v1.2.3 From aff0564aa7b2118a1d76dc0118dfdbf4beaf4b8c Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:26 -0700 Subject: NFC: trf7970a: Clear possible spurious interrupt before transmitting The trf7970a occasionally generates spurious interrupts which can confuse the driver. To help alleviate this, clear any interrupts by reading the 'IRQ Status Register' before starting a new transaction. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index b67946c18b40..e7f22a44dc52 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1120,6 +1120,7 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, char *prefix; unsigned int len; int ret; + u8 status; dev_dbg(trf->dev, "New request - state: %d, timeout: %d ms, len: %d\n", trf->state, timeout, skb->len); @@ -1195,6 +1196,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, len = min_t(int, skb->len, TRF7970A_FIFO_SIZE); + /* Clear possible spurious interrupt */ + ret = trf7970a_read_irqstatus(trf, &status); + if (ret) + goto out_err; + ret = trf7970a_transmit(trf, skb, len); if (ret) { kfree_skb(trf->rx_skb); -- cgit v1.2.3 From 5974150dead6da1db415f04a232f79b922f412a0 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:27 -0700 Subject: NFC: trf7970a: Remove unnecessary FIFO reset & RSSI read It is no longer necessary to reset the FIFO and read the 'RSSI Levels and Oscillator Status Register' so remove that code. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index e7f22a44dc52..c6216c1cc4b9 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -478,8 +478,6 @@ static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status) static void trf7970a_send_upstream(struct trf7970a *trf) { - u8 rssi; - dev_kfree_skb_any(trf->tx_skb); trf->tx_skb = NULL; @@ -488,13 +486,6 @@ static void trf7970a_send_upstream(struct trf7970a *trf) 16, 1, trf->rx_skb->data, trf->rx_skb->len, false); - /* According to the manual it is "good form" to reset the fifo and - * read the RSSI levels & oscillator status register here. It doesn't - * explain why. - */ - trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); - trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi); - trf->state = TRF7970A_ST_IDLE; if (trf->aborting) { -- cgit v1.2.3 From 7a1e5552af61dce180f70c6fafe31553254b3728 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:28 -0700 Subject: NFC: trf7970a: Prefix TX data when refilling FIFO When refilling the FIFO with more TX data (using a new SPI transaction), the driver must prefix the TX data with a write to the FIFO I/O Register. This tells the trf7970a that the following data is destined for the FIFO so it can be transmitted. To accomplish this, the driver cannot simply push the prefix data just before the next set of TX data that is to be transmitted because that will overwrite part of the TX data provided by the digital layer. Instead, separate the prefix data and the TX data when calling trf7970a_transmit(). trf7970a_transmit() can then send the prefix and TX data from different memory locations with one spi_sync() operation. This also means that the driver doesn't require any skb "tx_headroom" as provided by the digital layer (see nfc_digital_allocate_device() and digital_skb_alloc()). Also ensure that the prefix is of type 'u8' and not 'char'. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index c6216c1cc4b9..8a13daf97747 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -125,13 +125,6 @@ #define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */ -/* TX data must be prefixed with a FIFO reset cmd, a cmd that depends - * on what the current framing is, the address of the TX length byte 1 - * register (0x1d), and the 2 byte length of the data to be transmitted. - * That totals 5 bytes. - */ -#define TRF7970A_TX_SKB_HEADROOM 5 - #define TRF7970A_RX_SKB_ALLOC_SIZE 256 #define TRF7970A_FIFO_SIZE 127 @@ -515,15 +508,29 @@ static void trf7970a_send_err_upstream(struct trf7970a *trf, int errno) } static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb, - unsigned int len) + unsigned int len, u8 *prefix, unsigned int prefix_len) { + struct spi_transfer t[2]; + struct spi_message m; unsigned int timeout; int ret; print_hex_dump_debug("trf7970a tx data: ", DUMP_PREFIX_NONE, 16, 1, skb->data, len, false); - ret = spi_write(trf->spi, skb->data, len); + spi_message_init(&m); + + memset(&t, 0, sizeof(t)); + + t[0].tx_buf = prefix; + t[0].len = prefix_len; + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = skb->data; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + ret = spi_sync(trf->spi, &m); if (ret) { dev_err(trf->dev, "%s - Can't send tx data: %d\n", __func__, ret); @@ -559,6 +566,7 @@ static void trf7970a_fill_fifo(struct trf7970a *trf) unsigned int len; int ret; u8 fifo_bytes; + u8 prefix; ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); if (ret) { @@ -574,7 +582,9 @@ static void trf7970a_fill_fifo(struct trf7970a *trf) len = TRF7970A_FIFO_SIZE - fifo_bytes; len = min(skb->len, len); - ret = trf7970a_transmit(trf, skb, len); + prefix = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_FIFO_IO_REGISTER; + + ret = trf7970a_transmit(trf, skb, len, &prefix, sizeof(prefix)); if (ret) trf7970a_send_err_upstream(trf, ret); } @@ -1108,7 +1118,7 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, nfc_digital_cmd_complete_t cb, void *arg) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); - char *prefix; + u8 prefix[5]; unsigned int len; int ret; u8 status; @@ -1164,11 +1174,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, trf->ignore_timeout = false; len = skb->len; - prefix = skb_push(skb, TRF7970A_TX_SKB_HEADROOM); /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends * on what the current framing is, the address of the TX length byte 1 * register (0x1d), and the 2 byte length of the data to be transmitted. + * That totals 5 bytes. */ prefix[0] = TRF7970A_CMD_BIT_CTRL | TRF7970A_CMD_BIT_OPCODE(TRF7970A_CMD_FIFO_RESET); @@ -1192,7 +1202,7 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, if (ret) goto out_err; - ret = trf7970a_transmit(trf, skb, len); + ret = trf7970a_transmit(trf, skb, len, prefix, sizeof(prefix)); if (ret) { kfree_skb(trf->rx_skb); trf->rx_skb = NULL; @@ -1377,8 +1387,7 @@ static int trf7970a_probe(struct spi_device *spi) trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, TRF7970A_SUPPORTED_PROTOCOLS, - NFC_DIGITAL_DRV_CAPS_IN_CRC, TRF7970A_TX_SKB_HEADROOM, - 0); + NFC_DIGITAL_DRV_CAPS_IN_CRC, 0, 0); if (!trf->ddev) { dev_err(trf->dev, "Can't allocate NFC digital device\n"); ret = -ENOMEM; -- cgit v1.2.3 From 0e840ed59ba79670b66bba8c1d50b6f67e72d3fb Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:29 -0700 Subject: NFC: trf7970a: Only fill FIFO if there is space Handle the case where trf7970a_fill_fifo() is called but there is no room in the FIFO for more TX data. When this happens, wait for another interrupt indicating that there is now space (and set a timer in case that interrupt never occurs). Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 8a13daf97747..e9e961fe6756 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -580,6 +580,12 @@ static void trf7970a_fill_fifo(struct trf7970a *trf) /* Calculate how much more data can be written to the fifo */ len = TRF7970A_FIFO_SIZE - fifo_bytes; + if (!len) { + schedule_delayed_work(&trf->timeout_work, + msecs_to_jiffies(TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT)); + return; + } + len = min(skb->len, len); prefix = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_FIFO_IO_REGISTER; -- cgit v1.2.3 From bece3c544fee62ba7750f70b214d612fd02dcc8f Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:30 -0700 Subject: NFC: trf7970a: Handle low-watermark IRQ when transmitting Commit 4dd836e46c3d ("NFC: trf7970a: Reset FIFO when 'End of TX' Interrupt Occurs") fixes the issue that it was meant to fix but adds the unfortunate side effect of causing the driver to report an error when the TX low-watermark level is passed during transmits. This can be fixed by checking whether the IRQ status indicates that the low-watermark has been passed when transmitting. If it has been passed and the FIFO is empty, then its safe to reset the FIFO. Otherwise, silently continue since another TX interrupt will be generated and the FIFO will be reset then. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index e9e961fe6756..6d2b06ddf191 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -667,7 +667,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) { struct trf7970a *trf = dev_id; int ret; - u8 status; + u8 status, fifo_bytes; mutex_lock(&trf->lock); @@ -720,6 +720,16 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) trf->ignore_timeout = !cancel_delayed_work(&trf->timeout_work); trf7970a_drain_fifo(trf, status); + } else if (status & TRF7970A_IRQ_STATUS_FIFO) { + ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, + &fifo_bytes); + + fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; + + if (ret) + trf7970a_send_err_upstream(trf, ret); + else if (!fifo_bytes) + trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); } else if (status == TRF7970A_IRQ_STATUS_TX) { trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); } else { -- cgit v1.2.3 From 5d8f759424d3d7da998a7a9eee702071c8e5d381 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:31 -0700 Subject: NFC: trf7970a: Reread FIFO Status Register when draining FIFO Receiving an interrupt whose Interrupt Status Register value has only the SRX bit set is supposed to mean that all of the data from the tag has been received. That turns out to not be true so we need to reread the FIFO Status Register to tell if there are any new bytes in the FIFO. If there are, continue receiving them; if there aren't, assume that the receive is complete and pass the data up. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 6d2b06ddf191..8c00827893f1 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -648,6 +648,21 @@ static void trf7970a_drain_fifo(struct trf7970a *trf, u8 status) status = TRF7970A_IRQ_STATUS_SRX; } else { trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA_CONT; + + ret = trf7970a_read(trf, TRF7970A_FIFO_STATUS, &fifo_bytes); + if (ret) { + trf7970a_send_err_upstream(trf, ret); + return; + } + + fifo_bytes &= ~TRF7970A_FIFO_STATUS_OVERFLOW; + + /* If there are bytes in the FIFO, set status to '0' so + * the if stmt below doesn't fire and the driver will wait + * for the trf7970a to generate another RX interrupt. + */ + if (fifo_bytes) + status = 0; } no_rx_data: -- cgit v1.2.3 From afa5b5f13e0e2372e440f3ab44620d4e10fca496 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:32 -0700 Subject: NFC: trf7970a: Ensure no more RX data before completing receive Depending on the interrupt status value given by the trf7970a, the driver may not know when a receive operation is complete. To handle this, the driver waits for a period of time in case the trf7970a interrupts it again indicating there are more RX data in the FIFO. It is possible that the timeout will occur when there are RX data in the FIFO but before the trf7970a has generated an interrupt to tell the driver about it. Handle this by calling trf7970a_drain_fifo() (instead of trf7970a_send_upstream() which just passes up the data gathered to far) to check if there are more data in the FIFO. If so, gather that data into the receive buffer. If not, pass the data collected so far upstream as before. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 8c00827893f1..2b1573fb6e9f 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -800,7 +800,7 @@ static void trf7970a_timeout_work_handler(struct work_struct *work) if (trf->ignore_timeout) trf->ignore_timeout = false; else if (trf->state == TRF7970A_ST_WAIT_FOR_RX_DATA_CONT) - trf7970a_send_upstream(trf); /* No more rx data so send up */ + trf7970a_drain_fifo(trf, TRF7970A_IRQ_STATUS_SRX); else if (trf->state == TRF7970A_ST_WAIT_TO_ISSUE_EOF) trf7970a_issue_eof(trf); else -- cgit v1.2.3 From 0a1de84205d3fe7baa3d013ebf703416b1919ecc Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:33 -0700 Subject: NFC: trf7970a: Return error code when turning on RF fails trf7970a_switch_rf_on() is currently a void function but turning on the RF could fail so it should return a return code. That return code should also be propagated back to the entity that initiated the action. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 2b1573fb6e9f..8c2fb62982c4 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -869,7 +869,7 @@ static void trf7970a_switch_rf_off(struct trf7970a *trf) pm_runtime_put_autosuspend(trf->dev); } -static void trf7970a_switch_rf_on(struct trf7970a *trf) +static int trf7970a_switch_rf_on(struct trf7970a *trf) { int ret; @@ -880,15 +880,18 @@ static void trf7970a_switch_rf_on(struct trf7970a *trf) ret = trf7970a_init(trf); if (ret) { dev_err(trf->dev, "%s - Can't initialize: %d\n", __func__, ret); - return; + return ret; } trf->state = TRF7970A_ST_IDLE; + + return 0; } static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + int ret = 0; dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on); @@ -897,7 +900,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) if (on) { switch (trf->state) { case TRF7970A_ST_OFF: - trf7970a_switch_rf_on(trf); + ret = trf7970a_switch_rf_on(trf); break; case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: @@ -906,6 +909,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) dev_err(trf->dev, "%s - Invalid request: %d %d\n", __func__, trf->state, on); trf7970a_switch_rf_off(trf); + ret = -EINVAL; } } else { switch (trf->state) { @@ -914,6 +918,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) default: dev_err(trf->dev, "%s - Invalid request: %d %d\n", __func__, trf->state, on); + ret = -EINVAL; /* FALLTHROUGH */ case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: @@ -922,7 +927,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) } mutex_unlock(&trf->lock); - return 0; + return ret; } static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) @@ -1040,8 +1045,11 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, mutex_lock(&trf->lock); - if (trf->state == TRF7970A_ST_OFF) - trf7970a_switch_rf_on(trf); + if (trf->state == TRF7970A_ST_OFF) { + ret = trf7970a_switch_rf_on(trf); + if (ret) + goto err_unlock; + } switch (type) { case NFC_DIGITAL_CONFIG_RF_TECH: @@ -1055,6 +1063,7 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, ret = -EINVAL; } +err_unlock: mutex_unlock(&trf->lock); return ret; } -- cgit v1.2.3 From b5e17d9b5bd7e53696bce21e38eec5b9bb8abb88 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:34 -0700 Subject: NFC: trf7970a: Rename TRF7970A_ST_OFF to TRF7970A_ST_RF_OFF Rename the 'TRF7970A_ST_OFF' state to 'TRF7970A_ST_RF_OFF' to make it clear that this state means that the RF is off and not the entire device. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 8c2fb62982c4..cda854b98cf3 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -332,7 +332,7 @@ (ISO15693_REQ_FLAG_SUB_CARRIER | ISO15693_REQ_FLAG_DATA_RATE) enum trf7970a_state { - TRF7970A_ST_OFF, + TRF7970A_ST_RF_OFF, TRF7970A_ST_IDLE, TRF7970A_ST_IDLE_RX_BLOCKED, TRF7970A_ST_WAIT_FOR_TX_FIFO, @@ -686,7 +686,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) mutex_lock(&trf->lock); - if (trf->state == TRF7970A_ST_OFF) { + if (trf->state == TRF7970A_ST_RF_OFF) { mutex_unlock(&trf->lock); return IRQ_NONE; } @@ -863,7 +863,7 @@ static void trf7970a_switch_rf_off(struct trf7970a *trf) trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl); trf->aborting = false; - trf->state = TRF7970A_ST_OFF; + trf->state = TRF7970A_ST_RF_OFF; pm_runtime_mark_last_busy(trf->dev); pm_runtime_put_autosuspend(trf->dev); @@ -899,7 +899,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) if (on) { switch (trf->state) { - case TRF7970A_ST_OFF: + case TRF7970A_ST_RF_OFF: ret = trf7970a_switch_rf_on(trf); break; case TRF7970A_ST_IDLE: @@ -913,7 +913,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) } } else { switch (trf->state) { - case TRF7970A_ST_OFF: + case TRF7970A_ST_RF_OFF: break; default: dev_err(trf->dev, "%s - Invalid request: %d %d\n", @@ -1045,7 +1045,7 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, mutex_lock(&trf->lock); - if (trf->state == TRF7970A_ST_OFF) { + if (trf->state == TRF7970A_ST_RF_OFF) { ret = trf7970a_switch_rf_on(trf); if (ret) goto err_unlock; @@ -1348,7 +1348,7 @@ static int trf7970a_probe(struct spi_device *spi) if (!trf) return -ENOMEM; - trf->state = TRF7970A_ST_OFF; + trf->state = TRF7970A_ST_RF_OFF; trf->dev = &spi->dev; trf->spi = spi; @@ -1507,7 +1507,7 @@ static int trf7970a_pm_runtime_suspend(struct device *dev) dev_dbg(dev, "Runtime suspend\n"); - if (trf->state != TRF7970A_ST_OFF) { + if (trf->state != TRF7970A_ST_RF_OFF) { dev_dbg(dev, "Can't suspend - not in OFF state (%d)\n", trf->state); return -EBUSY; -- cgit v1.2.3 From ceccd6aa50887352e66d0edf68d8be510a639da6 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:35 -0700 Subject: NFC: trf7970a: Don't assume CONFIG_PM_RUNTIME is enabled The current code assumes that CONFIG_PM_RUNTIME is always defined so it won't power up the trf7970a when it isn't enabled. Fix this by moving the power up/down code from the pm_runtime_resume/suspend routines into their own routines and calling the power up function from the probe routine. This ensures the device is powered up even when CONFIG_PM_RUNTIME is not defined. In order to not power on/off a device that is already powered on/off, create a new state to indicate that the power is off (TRF7970A_ST_PWR_OFF). Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 132 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 36 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index cda854b98cf3..84a9c3f78621 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -332,6 +332,7 @@ (ISO15693_REQ_FLAG_SUB_CARRIER | ISO15693_REQ_FLAG_DATA_RATE) enum trf7970a_state { + TRF7970A_ST_PWR_OFF, TRF7970A_ST_RF_OFF, TRF7970A_ST_IDLE, TRF7970A_ST_IDLE_RX_BLOCKED, @@ -877,6 +878,12 @@ static int trf7970a_switch_rf_on(struct trf7970a *trf) pm_runtime_get_sync(trf->dev); + if (trf->state != TRF7970A_ST_RF_OFF) { /* Power on, RF off */ + dev_err(trf->dev, "%s - Incorrect state: %d\n", __func__, + trf->state); + return -EINVAL; + } + ret = trf7970a_init(trf); if (ret) { dev_err(trf->dev, "%s - Can't initialize: %d\n", __func__, ret); @@ -899,6 +906,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) if (on) { switch (trf->state) { + case TRF7970A_ST_PWR_OFF: case TRF7970A_ST_RF_OFF: ret = trf7970a_switch_rf_on(trf); break; @@ -913,6 +921,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) } } else { switch (trf->state) { + case TRF7970A_ST_PWR_OFF: case TRF7970A_ST_RF_OFF: break; default: @@ -1045,7 +1054,8 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, mutex_lock(&trf->lock); - if (trf->state == TRF7970A_ST_RF_OFF) { + if ((trf->state == TRF7970A_ST_PWR_OFF) || + (trf->state == TRF7970A_ST_RF_OFF)) { ret = trf7970a_switch_rf_on(trf); if (ret) goto err_unlock; @@ -1316,6 +1326,65 @@ static struct nfc_digital_ops trf7970a_nfc_ops = { .abort_cmd = trf7970a_abort_cmd, }; +static int trf7970a_power_up(struct trf7970a *trf) +{ + int ret; + + dev_dbg(trf->dev, "Powering up - state: %d\n", trf->state); + + if (trf->state != TRF7970A_ST_PWR_OFF) + return 0; + + ret = regulator_enable(trf->regulator); + if (ret) { + dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret); + return ret; + } + + usleep_range(5000, 6000); + + if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) { + gpio_set_value(trf->en2_gpio, 1); + usleep_range(1000, 2000); + } + + gpio_set_value(trf->en_gpio, 1); + + usleep_range(20000, 21000); + + trf->state = TRF7970A_ST_RF_OFF; + + return 0; +} + +static int trf7970a_power_down(struct trf7970a *trf) +{ + int ret; + + dev_dbg(trf->dev, "Powering down - state: %d\n", trf->state); + + if (trf->state == TRF7970A_ST_PWR_OFF) + return 0; + + if (trf->state != TRF7970A_ST_RF_OFF) { + dev_dbg(trf->dev, "Can't power down - not RF_OFF state (%d)\n", + trf->state); + return -EBUSY; + } + + gpio_set_value(trf->en_gpio, 0); + gpio_set_value(trf->en2_gpio, 0); + + ret = regulator_disable(trf->regulator); + if (ret) + dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__, + ret); + + trf->state = TRF7970A_ST_PWR_OFF; + + return ret; +} + static int trf7970a_get_autosuspend_delay(struct device_node *np) { int autosuspend_delay, ret; @@ -1348,7 +1417,7 @@ static int trf7970a_probe(struct spi_device *spi) if (!trf) return -ENOMEM; - trf->state = TRF7970A_ST_RF_OFF; + trf->state = TRF7970A_ST_PWR_OFF; trf->dev = &spi->dev; trf->spi = spi; @@ -1442,19 +1511,29 @@ static int trf7970a_probe(struct spi_device *spi) pm_runtime_set_autosuspend_delay(trf->dev, autosuspend_delay); pm_runtime_use_autosuspend(trf->dev); + + ret = trf7970a_power_up(trf); + if (ret) + goto err_free_ddev; + + pm_runtime_set_active(trf->dev); pm_runtime_enable(trf->dev); + pm_runtime_mark_last_busy(trf->dev); ret = nfc_digital_register_device(trf->ddev); if (ret) { dev_err(trf->dev, "Can't register NFC digital device: %d\n", ret); - goto err_free_ddev; + goto err_power_down; } return 0; -err_free_ddev: +err_power_down: pm_runtime_disable(trf->dev); + pm_runtime_set_suspended(trf->dev); + trf7970a_power_down(trf); +err_free_ddev: nfc_digital_free_device(trf->ddev); err_disable_regulator: regulator_disable(trf->regulator); @@ -1478,15 +1557,18 @@ static int trf7970a_remove(struct spi_device *spi) /* FALLTHROUGH */ case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: - pm_runtime_put_sync(trf->dev); + trf7970a_switch_rf_off(trf); break; default: break; } - mutex_unlock(&trf->lock); - pm_runtime_disable(trf->dev); + pm_runtime_set_suspended(trf->dev); + + trf7970a_power_down(trf); + + mutex_unlock(&trf->lock); nfc_digital_unregister_device(trf->ddev); nfc_digital_free_device(trf->ddev); @@ -1507,18 +1589,11 @@ static int trf7970a_pm_runtime_suspend(struct device *dev) dev_dbg(dev, "Runtime suspend\n"); - if (trf->state != TRF7970A_ST_RF_OFF) { - dev_dbg(dev, "Can't suspend - not in OFF state (%d)\n", - trf->state); - return -EBUSY; - } + mutex_lock(&trf->lock); - gpio_set_value(trf->en_gpio, 0); - gpio_set_value(trf->en2_gpio, 0); + ret = trf7970a_power_down(trf); - ret = regulator_disable(trf->regulator); - if (ret) - dev_err(dev, "%s - Can't disable VIN: %d\n", __func__, ret); + mutex_unlock(&trf->lock); return ret; } @@ -1531,26 +1606,11 @@ static int trf7970a_pm_runtime_resume(struct device *dev) dev_dbg(dev, "Runtime resume\n"); - ret = regulator_enable(trf->regulator); - if (ret) { - dev_err(dev, "%s - Can't enable VIN: %d\n", __func__, ret); - return ret; - } - - usleep_range(5000, 6000); - - if (!(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) { - gpio_set_value(trf->en2_gpio, 1); - usleep_range(1000, 2000); - } - - gpio_set_value(trf->en_gpio, 1); - - usleep_range(20000, 21000); + ret = trf7970a_power_up(trf); + if (!ret) + pm_runtime_mark_last_busy(dev); - pm_runtime_mark_last_busy(dev); - - return 0; + return ret; } #endif -- cgit v1.2.3 From b528281b8b7a9c379baf37720191a799fbc9800c Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:36 -0700 Subject: NFC: trf7970a: Create startup and shutdown routines Encapsulate the code to start up and gracefully shutdown the driver and trf7970a device. Doing this makes adding system suspend/resume support easier and the resulting code cleaner. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 72 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 29 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 84a9c3f78621..a42675da0667 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1385,6 +1385,44 @@ static int trf7970a_power_down(struct trf7970a *trf) return ret; } +static int trf7970a_startup(struct trf7970a *trf) +{ + int ret; + + ret = trf7970a_power_up(trf); + if (ret) + return ret; + + pm_runtime_set_active(trf->dev); + pm_runtime_enable(trf->dev); + pm_runtime_mark_last_busy(trf->dev); + + return 0; +} + +static void trf7970a_shutdown(struct trf7970a *trf) +{ + switch (trf->state) { + case TRF7970A_ST_WAIT_FOR_TX_FIFO: + case TRF7970A_ST_WAIT_FOR_RX_DATA: + case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: + case TRF7970A_ST_WAIT_TO_ISSUE_EOF: + trf7970a_send_err_upstream(trf, -ECANCELED); + /* FALLTHROUGH */ + case TRF7970A_ST_IDLE: + case TRF7970A_ST_IDLE_RX_BLOCKED: + trf7970a_switch_rf_off(trf); + break; + default: + break; + } + + pm_runtime_disable(trf->dev); + pm_runtime_set_suspended(trf->dev); + + trf7970a_power_down(trf); +} + static int trf7970a_get_autosuspend_delay(struct device_node *np) { int autosuspend_delay, ret; @@ -1512,27 +1550,21 @@ static int trf7970a_probe(struct spi_device *spi) pm_runtime_set_autosuspend_delay(trf->dev, autosuspend_delay); pm_runtime_use_autosuspend(trf->dev); - ret = trf7970a_power_up(trf); + ret = trf7970a_startup(trf); if (ret) goto err_free_ddev; - pm_runtime_set_active(trf->dev); - pm_runtime_enable(trf->dev); - pm_runtime_mark_last_busy(trf->dev); - ret = nfc_digital_register_device(trf->ddev); if (ret) { dev_err(trf->dev, "Can't register NFC digital device: %d\n", ret); - goto err_power_down; + goto err_shutdown; } return 0; -err_power_down: - pm_runtime_disable(trf->dev); - pm_runtime_set_suspended(trf->dev); - trf7970a_power_down(trf); +err_shutdown: + trf7970a_shutdown(trf); err_free_ddev: nfc_digital_free_device(trf->ddev); err_disable_regulator: @@ -1548,25 +1580,7 @@ static int trf7970a_remove(struct spi_device *spi) mutex_lock(&trf->lock); - switch (trf->state) { - case TRF7970A_ST_WAIT_FOR_TX_FIFO: - case TRF7970A_ST_WAIT_FOR_RX_DATA: - case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: - case TRF7970A_ST_WAIT_TO_ISSUE_EOF: - trf7970a_send_err_upstream(trf, -ECANCELED); - /* FALLTHROUGH */ - case TRF7970A_ST_IDLE: - case TRF7970A_ST_IDLE_RX_BLOCKED: - trf7970a_switch_rf_off(trf); - break; - default: - break; - } - - pm_runtime_disable(trf->dev); - pm_runtime_set_suspended(trf->dev); - - trf7970a_power_down(trf); + trf7970a_shutdown(trf); mutex_unlock(&trf->lock); -- cgit v1.2.3 From 77c9539dc1284677539af442ac3629c9baf01202 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:37 -0700 Subject: NFC: trf7970a: Add System Suspend/Resume support Add system suspend/resume support by gracefully shutting things down when suspending and bringing the device back to full power when resuming. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index a42675da0667..3859e02c4e2d 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1594,6 +1594,42 @@ static int trf7970a_remove(struct spi_device *spi) return 0; } +#ifdef CONFIG_PM_SLEEP +static int trf7970a_suspend(struct device *dev) +{ + struct spi_device *spi = container_of(dev, struct spi_device, dev); + struct trf7970a *trf = spi_get_drvdata(spi); + int ret = 0; + + dev_dbg(dev, "Suspend\n"); + + mutex_lock(&trf->lock); + + trf7970a_shutdown(trf); + + mutex_unlock(&trf->lock); + + return ret; +} + +static int trf7970a_resume(struct device *dev) +{ + struct spi_device *spi = container_of(dev, struct spi_device, dev); + struct trf7970a *trf = spi_get_drvdata(spi); + int ret = 0; + + dev_dbg(dev, "Resume\n"); + + mutex_lock(&trf->lock); + + ret = trf7970a_startup(trf); + + mutex_unlock(&trf->lock); + + return ret; +} +#endif + #ifdef CONFIG_PM_RUNTIME static int trf7970a_pm_runtime_suspend(struct device *dev) { @@ -1629,6 +1665,7 @@ static int trf7970a_pm_runtime_resume(struct device *dev) #endif static const struct dev_pm_ops trf7970a_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(trf7970a_suspend, trf7970a_resume) SET_RUNTIME_PM_OPS(trf7970a_pm_runtime_suspend, trf7970a_pm_runtime_resume, NULL) }; -- cgit v1.2.3 From 4e007f810664541078e619d050f6290bf137aa61 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:38 -0700 Subject: NFC: trf7970a: Delay after initialization The trf7970a should be given at least 1 ms to completely initialize after the 'Software Init' and 'Idle' commands have been issued. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 3859e02c4e2d..b2d0fbf70073 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -824,6 +824,8 @@ static int trf7970a_init(struct trf7970a *trf) if (ret) goto err_out; + usleep_range(1000, 2000); + ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 0); if (ret) goto err_out; -- cgit v1.2.3 From 307e5caf6fb1dac1b9cfa1d78138d77e46517b56 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:39 -0700 Subject: NFC: trf7970a: Add '_in_' to initiator routines Rename trf7970a_config_rf_tech() and trf7970a_config_framing() to trf7970a_in_config_rf_tech() and trf7970a_in_config_framing(), respectively to avoid confusion when target support is added. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index b2d0fbf70073..e4671e54424a 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -941,7 +941,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) return ret; } -static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) +static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech) { int ret = 0; @@ -983,7 +983,7 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) return ret; } -static int trf7970a_config_framing(struct trf7970a *trf, int framing) +static int trf7970a_in_config_framing(struct trf7970a *trf, int framing) { u8 iso_ctrl = trf->iso_ctrl_tech; int ret; @@ -1065,10 +1065,10 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, switch (type) { case NFC_DIGITAL_CONFIG_RF_TECH: - ret = trf7970a_config_rf_tech(trf, param); + ret = trf7970a_in_config_rf_tech(trf, param); break; case NFC_DIGITAL_CONFIG_FRAMING: - ret = trf7970a_config_framing(trf, param); + ret = trf7970a_in_config_framing(trf, param); break; default: dev_dbg(trf->dev, "Unknown type: %d\n", type); -- cgit v1.2.3 From cfc708dbe4022324bcd2bcb5817dd29f1f91299d Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:40 -0700 Subject: NFC: trf7970a: Don't turn off RF if its already off Don't try to turn off of RF transmitter is its already off. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index e4671e54424a..429146b7e6d8 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -859,6 +859,10 @@ err_out: static void trf7970a_switch_rf_off(struct trf7970a *trf) { + if ((trf->state == TRF7970A_ST_PWR_OFF) || + (trf->state == TRF7970A_ST_RF_OFF)) + return; + dev_dbg(trf->dev, "Switching rf off\n"); trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; -- cgit v1.2.3 From 7149d6bfecadc255e9d964782a9fdd70f610f1ea Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:41 -0700 Subject: NFC: trf7970a: trf7970a_init() turns off the RF transmitter When trf7970a_init() initializes the trf7970a it implicitly turns off the RF transmitter. Track this by clearing the TRF7970A_CHIP_STATUS_RF_ON bit in the cached trf->chip_status_ctrl. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 429146b7e6d8..ab6e276be6a6 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -826,6 +826,8 @@ static int trf7970a_init(struct trf7970a *trf) usleep_range(1000, 2000); + trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; + ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, 0); if (ret) goto err_out; -- cgit v1.2.3 From 851ee3cbf850501104e76683e439a4061f378a96 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:42 -0700 Subject: NFC: trf7970a: Don't turn on RF if there is already an RF field Currently, the trf7970a driver blindly turns on its RF field when configuring its framing. This isn't a good idea if there is already a device generating an RF field. Instead, check if there is already an RF field present before turning on this device's RF field and, if there is, return EBUSY. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index ab6e276be6a6..0f09278ec37a 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -164,8 +164,8 @@ #define TRF7970A_CMD_CLOSE_SLOT 0x15 #define TRF7970A_CMD_BLOCK_RX 0x16 #define TRF7970A_CMD_ENABLE_RX 0x17 -#define TRF7970A_CMD_TEST_EXT_RF 0x18 -#define TRF7970A_CMD_TEST_INT_RF 0x19 +#define TRF7970A_CMD_TEST_INT_RF 0x18 +#define TRF7970A_CMD_TEST_EXT_RF 0x19 #define TRF7970A_CMD_RX_GAIN_ADJUST 0x1a /* Bits determining whether its a direct command or register R/W, @@ -280,6 +280,10 @@ TRF7970A_IRQ_STATUS_PARITY_ERROR | \ TRF7970A_IRQ_STATUS_CRC_ERROR) +#define TRF7970A_RSSI_OSC_STATUS_RSSI_MASK (BIT(2) | BIT(1) | BIT(0)) +#define TRF7970A_RSSI_OSC_STATUS_RSSI_X_MASK (BIT(5) | BIT(4) | BIT(3)) +#define TRF7970A_RSSI_OSC_STATUS_RSSI_OSC_OK BIT(6) + #define TRF7970A_SPECIAL_FCN_REG1_COL_7_6 BIT(0) #define TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL BIT(1) #define TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX BIT(2) @@ -989,9 +993,43 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech) return ret; } +static int trf7970a_is_rf_field(struct trf7970a *trf, bool *is_rf_field) +{ + int ret; + u8 rssi; + + ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, + trf->chip_status_ctrl | TRF7970A_CHIP_STATUS_REC_ON); + if (ret) + return ret; + + ret = trf7970a_cmd(trf, TRF7970A_CMD_TEST_EXT_RF); + if (ret) + return ret; + + usleep_range(50, 60); + + ret = trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi); + if (ret) + return ret; + + ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, + trf->chip_status_ctrl); + if (ret) + return ret; + + if (rssi & TRF7970A_RSSI_OSC_STATUS_RSSI_MASK) + *is_rf_field = true; + else + *is_rf_field = false; + + return 0; +} + static int trf7970a_in_config_framing(struct trf7970a *trf, int framing) { u8 iso_ctrl = trf->iso_ctrl_tech; + bool is_rf_field = false; int ret; dev_dbg(trf->dev, "framing: %d\n", framing); @@ -1024,6 +1062,15 @@ static int trf7970a_in_config_framing(struct trf7970a *trf, int framing) trf->framing = framing; + if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) { + ret = trf7970a_is_rf_field(trf, &is_rf_field); + if (ret) + return ret; + + if (is_rf_field) + return -EBUSY; + } + if (iso_ctrl != trf->iso_ctrl) { ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); if (ret) -- cgit v1.2.3 From 6fb9edcb43d0b1bf0ac2aaf6ba488d105c45f477 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:43 -0700 Subject: NFC: trf7970a: Cancel timer when error encountered Some paths leave a timer still running when trf7970a_send_err_upstream() is called. This can cause a timeout to occur in a subsequent transaction making it fail. Fix this by ensuring there is no timer running before sending an error upstream. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 0f09278ec37a..00fb2cee6790 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -506,6 +506,8 @@ static void trf7970a_send_err_upstream(struct trf7970a *trf, int errno) { dev_dbg(trf->dev, "Error - state: %d, errno: %d\n", trf->state, errno); + cancel_delayed_work(&trf->timeout_work); + kfree_skb(trf->rx_skb); trf->rx_skb = ERR_PTR(errno); -- cgit v1.2.3 From 1961843ceeca0d3e55744bba7ae8d9e23d04cf6a Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:44 -0700 Subject: NFC: trf7970a: Handle timeout values of zero The digital layer can try to send a command with a timeout value of zero (e.g., digital_tg_send_psl_res(). The zero value is used as a flag to indicate that the driver should not expect a response. To handle this, the driver sets an internal timer because it should still get an interrupt with the TX bit set in the IRQ Status Register. When it gets that interrupt, it returns a return value of '0'. If it doesn't get the interrupt before timing out, it returns ETIMEDOUT as usual. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 00fb2cee6790..8b109e15687f 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -132,6 +132,7 @@ /* TX length is 3 nibbles long ==> 4KB - 1 bytes max */ #define TRF7970A_TX_MAX (4096 - 1) +#define TRF7970A_WAIT_FOR_TX_IRQ 20 #define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 20 #define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 20 #define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 40 @@ -555,7 +556,11 @@ static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb, timeout = TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF; } else { trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA; - timeout = trf->timeout; + + if (!trf->timeout) + timeout = TRF7970A_WAIT_FOR_TX_IRQ; + else + timeout = trf->timeout; } } @@ -754,6 +759,14 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); } else if (status == TRF7970A_IRQ_STATUS_TX) { trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); + + if (!trf->timeout) { + trf->ignore_timeout = !cancel_delayed_work( + &trf->timeout_work); + trf->rx_skb = ERR_PTR(0); + trf7970a_send_upstream(trf); + break; + } } else { trf7970a_send_err_upstream(trf, -EIO); } @@ -1253,12 +1266,14 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, goto out_err; } - trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE, - GFP_KERNEL); - if (!trf->rx_skb) { - dev_dbg(trf->dev, "Can't alloc rx_skb\n"); - ret = -ENOMEM; - goto out_err; + if (timeout) { + trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE, + GFP_KERNEL); + if (!trf->rx_skb) { + dev_dbg(trf->dev, "Can't alloc rx_skb\n"); + ret = -ENOMEM; + goto out_err; + } } if (trf->state == TRF7970A_ST_IDLE_RX_BLOCKED) { -- cgit v1.2.3 From 13b4272a8264220ec043a922fd1fa05da72d57ae Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:45 -0700 Subject: NFC: trf7970a: Add Target Mode Support Add target mode support to the trf7970a NFC driver. This effectively enables full Peer-to-Peer support. To handle changing framing between sending a response frame and receiving the subsequent request frame, most of the framing changes take effect in the interrupt handler and not in trf7970a_tg_config_framing(). Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 374 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 339 insertions(+), 35 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 8b109e15687f..b33cc0211f53 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -62,7 +62,7 @@ * way to abort a command that's already been sent to the tag is so turn * off power to the tag. If we do that, though, we'd have to go through * the entire anticollision procedure again but the digital layer doesn't - * support that. So, if an abort is received before trf7970a_in_send_cmd() + * support that. So, if an abort is received before trf7970a_send_cmd() * has sent the command to the tag, it simply returns -ECANCELED. If the * command has already been sent to the tag, then the driver continues * normally and recieves the response data (or error) but just before @@ -121,7 +121,7 @@ #define TRF7970A_SUPPORTED_PROTOCOLS \ (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_FELICA_MASK | \ - NFC_PROTO_ISO15693_MASK) + NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK) #define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */ @@ -240,6 +240,15 @@ #define TRF7970A_ISO_CTRL_14443B_848 0x0f #define TRF7970A_ISO_CTRL_FELICA_212 0x1a #define TRF7970A_ISO_CTRL_FELICA_424 0x1b +#define TRF7970A_ISO_CTRL_NFC_NFCA_106 0x01 +#define TRF7970A_ISO_CTRL_NFC_NFCF_212 0x02 +#define TRF7970A_ISO_CTRL_NFC_NFCF_424 0x03 +#define TRF7970A_ISO_CTRL_NFC_CE_14443A 0x00 +#define TRF7970A_ISO_CTRL_NFC_CE_14443B 0x01 +#define TRF7970A_ISO_CTRL_NFC_CE BIT(2) +#define TRF7970A_ISO_CTRL_NFC_ACTIVE BIT(3) +#define TRF7970A_ISO_CTRL_NFC_INITIATOR BIT(4) +#define TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE BIT(5) #define TRF7970A_ISO_CTRL_RFID BIT(5) #define TRF7970A_ISO_CTRL_DIR_MODE BIT(6) #define TRF7970A_ISO_CTRL_RX_CRC_N BIT(7) /* true == No CRC */ @@ -265,12 +274,32 @@ #define TRF7970A_MODULATOR_EN_OOK BIT(6) #define TRF7970A_MODULATOR_27MHZ BIT(7) +#define TRF7970A_RX_SPECIAL_SETTINGS_NO_LIM BIT(0) +#define TRF7970A_RX_SPECIAL_SETTINGS_AGCR BIT(1) +#define TRF7970A_RX_SPECIAL_SETTINGS_GD_0DB (0x0 << 2) +#define TRF7970A_RX_SPECIAL_SETTINGS_GD_5DB (0x1 << 2) +#define TRF7970A_RX_SPECIAL_SETTINGS_GD_10DB (0x2 << 2) +#define TRF7970A_RX_SPECIAL_SETTINGS_GD_15DB (0x3 << 2) +#define TRF7970A_RX_SPECIAL_SETTINGS_HBT BIT(4) +#define TRF7970A_RX_SPECIAL_SETTINGS_M848 BIT(5) +#define TRF7970A_RX_SPECIAL_SETTINGS_C424 BIT(6) +#define TRF7970A_RX_SPECIAL_SETTINGS_C212 BIT(7) + +#define TRF7970A_REG_IO_CTRL_VRS(v) ((v) & 0x07) +#define TRF7970A_REG_IO_CTRL_IO_LOW BIT(5) +#define TRF7970A_REG_IO_CTRL_EN_EXT_PA BIT(6) +#define TRF7970A_REG_IO_CTRL_AUTO_REG BIT(7) + /* IRQ Status Register Bits */ #define TRF7970A_IRQ_STATUS_NORESP BIT(0) /* ISO15693 only */ +#define TRF7970A_IRQ_STATUS_NFC_COL_ERROR BIT(0) #define TRF7970A_IRQ_STATUS_COL BIT(1) #define TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR BIT(2) +#define TRF7970A_IRQ_STATUS_NFC_RF BIT(2) #define TRF7970A_IRQ_STATUS_PARITY_ERROR BIT(3) +#define TRF7970A_IRQ_STATUS_NFC_SDD BIT(3) #define TRF7970A_IRQ_STATUS_CRC_ERROR BIT(4) +#define TRF7970A_IRQ_STATUS_NFC_PROTO_ERROR BIT(4) #define TRF7970A_IRQ_STATUS_FIFO BIT(5) #define TRF7970A_IRQ_STATUS_SRX BIT(6) #define TRF7970A_IRQ_STATUS_TX BIT(7) @@ -301,6 +330,16 @@ #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_16 0x2 #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32 0x3 +#define TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(v) ((v) & 0x07) +#define TRF7970A_NFC_LOW_FIELD_LEVEL_CLEX_DIS BIT(7) + +#define TRF7970A_NFC_TARGET_LEVEL_RFDET(v) ((v) & 0x07) +#define TRF7970A_NFC_TARGET_LEVEL_HI_RF BIT(3) +#define TRF7970A_NFC_TARGET_LEVEL_SDD_EN BIT(3) +#define TRF7970A_NFC_TARGET_LEVEL_LD_S_4BYTES (0x0 << 6) +#define TRF7970A_NFC_TARGET_LEVEL_LD_S_7BYTES (0x1 << 6) +#define TRF7970A_NFC_TARGET_LEVEL_LD_S_10BYTES (0x2 << 6) + #define TRF7970A_FIFO_STATUS_OVERFLOW BIT(7) /* NFC (ISO/IEC 14443A) Type 2 Tag commands */ @@ -345,6 +384,7 @@ enum trf7970a_state { TRF7970A_ST_WAIT_FOR_RX_DATA, TRF7970A_ST_WAIT_FOR_RX_DATA_CONT, TRF7970A_ST_WAIT_TO_ISSUE_EOF, + TRF7970A_ST_LISTENING, TRF7970A_ST_MAX }; @@ -355,6 +395,7 @@ struct trf7970a { struct regulator *regulator; struct nfc_digital_dev *ddev; u32 quirks; + bool is_initiator; bool aborting; struct sk_buff *tx_skb; struct sk_buff *rx_skb; @@ -694,7 +735,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) { struct trf7970a *trf = dev_id; int ret; - u8 status, fifo_bytes; + u8 status, fifo_bytes, iso_ctrl; mutex_lock(&trf->lock); @@ -720,12 +761,12 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) switch (trf->state) { case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: - /* If getting interrupts caused by RF noise, turn off the - * receiver to avoid unnecessary interrupts. It will be - * turned back on in trf7970a_in_send_cmd() when the next - * command is issued. + /* If initiator and getting interrupts caused by RF noise, + * turn off the receiver to avoid unnecessary interrupts. + * It will be turned back on in trf7970a_send_cmd() when + * the next command is issued. */ - if (status & TRF7970A_IRQ_STATUS_ERROR) { + if (trf->is_initiator && (status & TRF7970A_IRQ_STATUS_ERROR)) { trf7970a_cmd(trf, TRF7970A_CMD_BLOCK_RX); trf->state = TRF7970A_ST_IDLE_RX_BLOCKED; } @@ -757,7 +798,10 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) trf7970a_send_err_upstream(trf, ret); else if (!fifo_bytes) trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); - } else if (status == TRF7970A_IRQ_STATUS_TX) { + } else if ((status == TRF7970A_IRQ_STATUS_TX) || + (!trf->is_initiator && + (status == (TRF7970A_IRQ_STATUS_TX | + TRF7970A_IRQ_STATUS_NFC_RF)))) { trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); if (!trf->timeout) { @@ -767,6 +811,45 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) trf7970a_send_upstream(trf); break; } + + if (trf->is_initiator) + break; + + iso_ctrl = trf->iso_ctrl; + + switch (trf->framing) { + case NFC_DIGITAL_FRAMING_NFCA_STANDARD: + trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; + iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; + trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */ + break; + case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: + trf->tx_cmd = TRF7970A_CMD_TRANSMIT; + iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; + trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */ + break; + case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE: + ret = trf7970a_write(trf, + TRF7970A_SPECIAL_FCN_REG1, + TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL); + if (ret) + return ret; + + trf->special_fcn_reg1 = + TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL; + break; + default: + break; + } + + if (iso_ctrl != trf->iso_ctrl) { + ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, + iso_ctrl); + if (ret) + return ret; + + trf->iso_ctrl = iso_ctrl; + } } else { trf7970a_send_err_upstream(trf, -EIO); } @@ -775,6 +858,15 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) if (status != TRF7970A_IRQ_STATUS_TX) trf7970a_send_err_upstream(trf, -EIO); break; + case TRF7970A_ST_LISTENING: + if (status & TRF7970A_IRQ_STATUS_SRX) { + trf->ignore_timeout = + !cancel_delayed_work(&trf->timeout_work); + trf7970a_drain_fifo(trf, status); + } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) { + trf7970a_send_err_upstream(trf, -EIO); + } + break; default: dev_err(trf->dev, "%s - Driver in invalid state: %d\n", __func__, trf->state); @@ -853,11 +945,6 @@ static int trf7970a_init(struct trf7970a *trf) trf->modulator_sys_clk_ctrl = 0; - /* Must clear NFC Target Detection Level reg due to erratum */ - ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); - if (ret) - goto err_out; - ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 | TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32); @@ -958,6 +1045,8 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) /* FALLTHROUGH */ case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: + case TRF7970A_ST_WAIT_FOR_RX_DATA: + case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: trf7970a_switch_rf_off(trf); } } @@ -1005,6 +1094,14 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech) trf->technology = tech; + /* If in initiator mode and not changing the RF tech due to a + * PSL sequence (indicated by 'trf->iso_ctrl == 0xff' from + * trf7970a_init()), clear the NFC Target Detection Level register + * due to erratum. + */ + if (trf->iso_ctrl == 0xff) + ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); + return ret; } @@ -1063,6 +1160,8 @@ static int trf7970a_in_config_framing(struct trf7970a *trf, int framing) case NFC_DIGITAL_FRAMING_NFCF_T3T: case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY: case NFC_DIGITAL_FRAMING_ISO15693_T5T: + case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP: + case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP: trf->tx_cmd = TRF7970A_CMD_TRANSMIT; iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; break; @@ -1124,6 +1223,8 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, mutex_lock(&trf->lock); + trf->is_initiator = true; + if ((trf->state == TRF7970A_ST_PWR_OFF) || (trf->state == TRF7970A_ST_RF_OFF)) { ret = trf7970a_switch_rf_on(trf); @@ -1233,7 +1334,7 @@ static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb) return 0; } -static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, +static int trf7970a_send_cmd(struct nfc_digital_dev *ddev, struct sk_buff *skb, u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) { @@ -1284,9 +1385,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev, trf->state = TRF7970A_ST_IDLE; } - ret = trf7970a_per_cmd_config(trf, skb); - if (ret) - goto out_err; + if (trf->is_initiator) { + ret = trf7970a_per_cmd_config(trf, skb); + if (ret) + goto out_err; + } trf->ddev = ddev; trf->tx_skb = skb; @@ -1335,35 +1438,229 @@ out_err: return ret; } -static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev, - int type, int param) +static int trf7970a_tg_config_rf_tech(struct trf7970a *trf, int tech) { - struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + int ret = 0; + + dev_dbg(trf->dev, "rf technology: %d\n", tech); + + switch (tech) { + case NFC_DIGITAL_RF_TECH_106A: + trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | + TRF7970A_ISO_CTRL_NFC_CE | + TRF7970A_ISO_CTRL_NFC_CE_14443A; + trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; + break; + case NFC_DIGITAL_RF_TECH_212F: + trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | + TRF7970A_ISO_CTRL_NFC_NFCF_212; + trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; + break; + case NFC_DIGITAL_RF_TECH_424F: + trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE | + TRF7970A_ISO_CTRL_NFC_NFCF_424; + trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; + break; + default: + dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); + return -EINVAL; + } + + trf->technology = tech; - dev_dbg(trf->dev, "Unsupported interface\n"); + /* Normally we write the ISO_CTRL register in + * trf7970a_tg_config_framing() because the framing can change + * the value written. However, when sending a PSL RES, + * digital_tg_send_psl_res_complete() doesn't call + * trf7970a_tg_config_framing() so we must write the register + * here. + */ + if ((trf->framing == NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED) && + (trf->iso_ctrl_tech != trf->iso_ctrl)) { + ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, + trf->iso_ctrl_tech); + + trf->iso_ctrl = trf->iso_ctrl_tech; + } - return -EINVAL; + return ret; } -static int trf7970a_tg_send_cmd(struct nfc_digital_dev *ddev, - struct sk_buff *skb, u16 timeout, - nfc_digital_cmd_complete_t cb, void *arg) +/* Since this is a target routine, several of the framing calls are + * made between receiving the request and sending the response so they + * should take effect until after the response is sent. This is accomplished + * by skipping the ISO_CTRL register write here and doing it in the interrupt + * handler. + */ +static int trf7970a_tg_config_framing(struct trf7970a *trf, int framing) +{ + u8 iso_ctrl = trf->iso_ctrl_tech; + int ret; + + dev_dbg(trf->dev, "framing: %d\n", framing); + + switch (framing) { + case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP: + trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; + iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; + break; + case NFC_DIGITAL_FRAMING_NFCA_STANDARD: + case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: + case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE: + /* These ones are applied in the interrupt handler */ + iso_ctrl = trf->iso_ctrl; /* Don't write to ISO_CTRL yet */ + break; + case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP: + trf->tx_cmd = TRF7970A_CMD_TRANSMIT; + iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; + break; + case NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED: + trf->tx_cmd = TRF7970A_CMD_TRANSMIT; + iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; + break; + default: + dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing); + return -EINVAL; + } + + trf->framing = framing; + + if (iso_ctrl != trf->iso_ctrl) { + ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); + if (ret) + return ret; + + trf->iso_ctrl = iso_ctrl; + + ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, + trf->modulator_sys_clk_ctrl); + if (ret) + return ret; + } + + if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) { + ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, + trf->chip_status_ctrl | + TRF7970A_CHIP_STATUS_RF_ON); + if (ret) + return ret; + + trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON; + } + + return 0; +} + +static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev, int type, + int param) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + int ret; + + dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param); + + mutex_lock(&trf->lock); + + trf->is_initiator = false; - dev_dbg(trf->dev, "Unsupported interface\n"); + if ((trf->state == TRF7970A_ST_PWR_OFF) || + (trf->state == TRF7970A_ST_RF_OFF)) { + ret = trf7970a_switch_rf_on(trf); + if (ret) + goto err_unlock; + } + + switch (type) { + case NFC_DIGITAL_CONFIG_RF_TECH: + ret = trf7970a_tg_config_rf_tech(trf, param); + break; + case NFC_DIGITAL_CONFIG_FRAMING: + ret = trf7970a_tg_config_framing(trf, param); + break; + default: + dev_dbg(trf->dev, "Unknown type: %d\n", type); + ret = -EINVAL; + } - return -EINVAL; +err_unlock: + mutex_unlock(&trf->lock); + return ret; } -static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, - u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) +static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + int ret; + + dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n", + trf->state, timeout); + + mutex_lock(&trf->lock); - dev_dbg(trf->dev, "Unsupported interface\n"); + if ((trf->state != TRF7970A_ST_IDLE) && + (trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) { + dev_err(trf->dev, "%s - Bogus state: %d\n", __func__, + trf->state); + ret = -EIO; + goto out_err; + } + + if (trf->aborting) { + dev_dbg(trf->dev, "Abort process complete\n"); + trf->aborting = false; + ret = -ECANCELED; + goto out_err; + } + + trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE, + GFP_KERNEL); + if (!trf->rx_skb) { + dev_dbg(trf->dev, "Can't alloc rx_skb\n"); + ret = -ENOMEM; + goto out_err; + } + + ret = trf7970a_write(trf, TRF7970A_RX_SPECIAL_SETTINGS, + TRF7970A_RX_SPECIAL_SETTINGS_HBT | + TRF7970A_RX_SPECIAL_SETTINGS_M848 | + TRF7970A_RX_SPECIAL_SETTINGS_C424 | + TRF7970A_RX_SPECIAL_SETTINGS_C212); + if (ret) + return ret; + + ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL, + TRF7970A_REG_IO_CTRL_VRS(0x1)); + if (ret) + return ret; - return -EINVAL; + ret = trf7970a_write(trf, TRF7970A_NFC_LOW_FIELD_LEVEL, + TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(0x3)); + if (ret) + return ret; + + ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, + TRF7970A_NFC_TARGET_LEVEL_RFDET(0x7)); + if (ret) + return ret; + + trf->ddev = ddev; + trf->cb = cb; + trf->cb_arg = arg; + trf->timeout = timeout; + trf->ignore_timeout = false; + + ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX); + if (ret) + goto out_err; + + trf->state = TRF7970A_ST_LISTENING; + + schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout)); + +out_err: + mutex_unlock(&trf->lock); + return ret; } static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) @@ -1381,6 +1678,11 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) case TRF7970A_ST_WAIT_TO_ISSUE_EOF: trf->aborting = true; break; + case TRF7970A_ST_LISTENING: + trf->ignore_timeout = !cancel_delayed_work(&trf->timeout_work); + trf7970a_send_err_upstream(trf, -ECANCELED); + dev_dbg(trf->dev, "Abort process complete\n"); + break; default: break; } @@ -1390,9 +1692,9 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) static struct nfc_digital_ops trf7970a_nfc_ops = { .in_configure_hw = trf7970a_in_configure_hw, - .in_send_cmd = trf7970a_in_send_cmd, + .in_send_cmd = trf7970a_send_cmd, .tg_configure_hw = trf7970a_tg_configure_hw, - .tg_send_cmd = trf7970a_tg_send_cmd, + .tg_send_cmd = trf7970a_send_cmd, .tg_listen = trf7970a_tg_listen, .switch_rf = trf7970a_switch_rf, .abort_cmd = trf7970a_abort_cmd, @@ -1479,6 +1781,7 @@ static void trf7970a_shutdown(struct trf7970a *trf) case TRF7970A_ST_WAIT_FOR_RX_DATA: case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: case TRF7970A_ST_WAIT_TO_ISSUE_EOF: + case TRF7970A_ST_LISTENING: trf7970a_send_err_upstream(trf, -ECANCELED); /* FALLTHROUGH */ case TRF7970A_ST_IDLE: @@ -1606,7 +1909,8 @@ static int trf7970a_probe(struct spi_device *spi) trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, TRF7970A_SUPPORTED_PROTOCOLS, - NFC_DIGITAL_DRV_CAPS_IN_CRC, 0, 0); + NFC_DIGITAL_DRV_CAPS_IN_CRC | + NFC_DIGITAL_DRV_CAPS_TG_CRC, 0, 0); if (!trf->ddev) { dev_err(trf->dev, "Can't allocate NFC digital device\n"); ret = -ENOMEM; -- cgit v1.2.3 From cb174aba86fe10ddac8b692c90a9480526c02953 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 2 Sep 2014 15:12:46 -0700 Subject: NFC: trf7970a: Add Target Mode Detection Support Add the ability to detect the mode (i.e., RF technology) used by the initiator. The RF technology that was detected can be retrieved by calling the 'tg_get_rf_tech' driver hook. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 154 insertions(+), 6 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index b33cc0211f53..2a521bb38060 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -340,6 +340,39 @@ #define TRF7970A_NFC_TARGET_LEVEL_LD_S_7BYTES (0x1 << 6) #define TRF7970A_NFC_TARGET_LEVEL_LD_S_10BYTES (0x2 << 6) +#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106 BIT(0) +#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212 BIT(1) +#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424 (BIT(0) | BIT(1)) +#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B BIT(2) +#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 BIT(3) +#define TRF79070A_NFC_TARGET_PROTOCOL_FELICA BIT(4) +#define TRF79070A_NFC_TARGET_PROTOCOL_RF_L BIT(6) +#define TRF79070A_NFC_TARGET_PROTOCOL_RF_H BIT(7) + +#define TRF79070A_NFC_TARGET_PROTOCOL_106A \ + (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ + TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ + TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 | \ + TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106) + +#define TRF79070A_NFC_TARGET_PROTOCOL_106B \ + (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ + TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ + TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B | \ + TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106) + +#define TRF79070A_NFC_TARGET_PROTOCOL_212F \ + (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ + TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ + TRF79070A_NFC_TARGET_PROTOCOL_FELICA | \ + TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212) + +#define TRF79070A_NFC_TARGET_PROTOCOL_424F \ + (TRF79070A_NFC_TARGET_PROTOCOL_RF_H | \ + TRF79070A_NFC_TARGET_PROTOCOL_RF_L | \ + TRF79070A_NFC_TARGET_PROTOCOL_FELICA | \ + TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424) + #define TRF7970A_FIFO_STATUS_OVERFLOW BIT(7) /* NFC (ISO/IEC 14443A) Type 2 Tag commands */ @@ -385,6 +418,7 @@ enum trf7970a_state { TRF7970A_ST_WAIT_FOR_RX_DATA_CONT, TRF7970A_ST_WAIT_TO_ISSUE_EOF, TRF7970A_ST_LISTENING, + TRF7970A_ST_LISTENING_MD, TRF7970A_ST_MAX }; @@ -409,6 +443,7 @@ struct trf7970a { unsigned int guard_time; int technology; int framing; + u8 md_rf_tech; u8 tx_cmd; bool issue_eof; int en2_gpio; @@ -516,6 +551,58 @@ static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status) return ret; } +static int trf7970a_read_target_proto(struct trf7970a *trf, u8 *target_proto) +{ + int ret; + u8 buf[2]; + u8 addr; + + addr = TRF79070A_NFC_TARGET_PROTOCOL | TRF7970A_CMD_BIT_RW | + TRF7970A_CMD_BIT_CONTINUOUS; + + ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2); + if (ret) + dev_err(trf->dev, "%s - target_proto: Read failed: %d\n", + __func__, ret); + else + *target_proto = buf[0]; + + return ret; +} + +static int trf7970a_mode_detect(struct trf7970a *trf, u8 *rf_tech) +{ + int ret; + u8 target_proto, tech; + + ret = trf7970a_read_target_proto(trf, &target_proto); + if (ret) + return ret; + + switch (target_proto) { + case TRF79070A_NFC_TARGET_PROTOCOL_106A: + tech = NFC_DIGITAL_RF_TECH_106A; + break; + case TRF79070A_NFC_TARGET_PROTOCOL_106B: + tech = NFC_DIGITAL_RF_TECH_106B; + break; + case TRF79070A_NFC_TARGET_PROTOCOL_212F: + tech = NFC_DIGITAL_RF_TECH_212F; + break; + case TRF79070A_NFC_TARGET_PROTOCOL_424F: + tech = NFC_DIGITAL_RF_TECH_424F; + break; + default: + dev_dbg(trf->dev, "%s - mode_detect: target_proto: 0x%x\n", + __func__, target_proto); + return -EIO; + } + + *rf_tech = tech; + + return ret; +} + static void trf7970a_send_upstream(struct trf7970a *trf) { dev_kfree_skb_any(trf->tx_skb); @@ -867,6 +954,22 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) trf7970a_send_err_upstream(trf, -EIO); } break; + case TRF7970A_ST_LISTENING_MD: + if (status & TRF7970A_IRQ_STATUS_SRX) { + trf->ignore_timeout = + !cancel_delayed_work(&trf->timeout_work); + + ret = trf7970a_mode_detect(trf, &trf->md_rf_tech); + if (ret) { + trf7970a_send_err_upstream(trf, ret); + } else { + trf->state = TRF7970A_ST_LISTENING; + trf7970a_drain_fifo(trf, status); + } + } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) { + trf7970a_send_err_upstream(trf, -EIO); + } + break; default: dev_err(trf->dev, "%s - Driver in invalid state: %d\n", __func__, trf->state); @@ -1587,15 +1690,12 @@ err_unlock: return ret; } -static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, - nfc_digital_cmd_complete_t cb, void *arg) +static int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg, bool mode_detect) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); int ret; - dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n", - trf->state, timeout); - mutex_lock(&trf->lock); if ((trf->state != TRF7970A_ST_IDLE) && @@ -1654,7 +1754,8 @@ static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, if (ret) goto out_err; - trf->state = TRF7970A_ST_LISTENING; + trf->state = mode_detect ? TRF7970A_ST_LISTENING_MD : + TRF7970A_ST_LISTENING; schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout)); @@ -1663,6 +1764,51 @@ out_err: return ret; } +static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, + nfc_digital_cmd_complete_t cb, void *arg) +{ + struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + + dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n", + trf->state, timeout); + + return _trf7970a_tg_listen(ddev, timeout, cb, arg, false); +} + +static int trf7970a_tg_listen_md(struct nfc_digital_dev *ddev, + u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) +{ + struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + int ret; + + dev_dbg(trf->dev, "Listen MD - state: %d, timeout: %d ms\n", + trf->state, timeout); + + ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, + NFC_DIGITAL_RF_TECH_106A); + if (ret) + return ret; + + ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, + NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); + if (ret) + return ret; + + return _trf7970a_tg_listen(ddev, timeout, cb, arg, true); +} + +static int trf7970a_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech) +{ + struct trf7970a *trf = nfc_digital_get_drvdata(ddev); + + dev_dbg(trf->dev, "Get RF Tech - state: %d, rf_tech: %d\n", + trf->state, trf->md_rf_tech); + + *rf_tech = trf->md_rf_tech; + + return 0; +} + static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) { struct trf7970a *trf = nfc_digital_get_drvdata(ddev); @@ -1696,6 +1842,8 @@ static struct nfc_digital_ops trf7970a_nfc_ops = { .tg_configure_hw = trf7970a_tg_configure_hw, .tg_send_cmd = trf7970a_send_cmd, .tg_listen = trf7970a_tg_listen, + .tg_listen_md = trf7970a_tg_listen_md, + .tg_get_rf_tech = trf7970a_tg_get_rf_tech, .switch_rf = trf7970a_switch_rf, .abort_cmd = trf7970a_abort_cmd, }; -- cgit v1.2.3 From ce3a5de7f58f18976b6536d8ea663f90da0e8093 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Mon, 28 Jul 2014 18:11:28 +0200 Subject: NFC: st21nfca: Remove double assignment of .owner in struct device_driver The .owner member of struct device_driver is assigned THIS_MODULE twice. Introduced by: commit c44cb2edd01ca31471d9385f0895891b006ab904 ("NFC: dts: st21nfca: Add device-tree (Open Firmware) support to st21nfca") Acked-by: Christophe RICARD Signed-off-by: Emil Goode Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/i2c.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index ff31939978ae..5d20ccf2e589 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -711,7 +711,6 @@ static struct i2c_driver st21nfca_hci_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = ST21NFCA_HCI_I2C_DRIVER_NAME, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_st21nfca_i2c_match), }, .probe = st21nfca_hci_i2c_probe, -- cgit v1.2.3 From 0be8ce737c1f052a1811d029f8afb03583f7238f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 28 Jul 2014 18:11:29 +0200 Subject: NFC: st21nfca: Convert to use devm_gpio_request_one This simplifies the code a bit. Acked-by: Christophe RICARD Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/i2c.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index 5d20ccf2e589..d7a2c7636e26 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -525,17 +525,13 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) } /* GPIO request and configuration */ - r = devm_gpio_request(&client->dev, gpio, "clf_enable"); + r = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH, + "clf_enable"); if (r) { nfc_err(&client->dev, "Failed to request enable pin\n"); return -ENODEV; } - r = gpio_direction_output(gpio, 1); - if (r) { - nfc_err(&client->dev, "Failed to set enable pin direction as output\n"); - return -ENODEV; - } phy->gpio_ena = gpio; /* IRQ */ @@ -576,32 +572,20 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client) phy->gpio_ena = pdata->gpio_ena; phy->irq_polarity = pdata->irq_polarity; - r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up"); + r = devm_gpio_request_one(&client->dev, phy->gpio_irq, GPIOF_IN, + "wake_up"); if (r) { pr_err("%s : gpio_request failed\n", __FILE__); return -ENODEV; } - r = gpio_direction_input(phy->gpio_irq); - if (r) { - pr_err("%s : gpio_direction_input failed\n", __FILE__); - return -ENODEV; - } - if (phy->gpio_ena > 0) { - r = devm_gpio_request(&client->dev, - phy->gpio_ena, "clf_enable"); + r = devm_gpio_request_one(&client->dev, phy->gpio_ena, + GPIOF_OUT_INIT_HIGH, "clf_enable"); if (r) { pr_err("%s : ena gpio_request failed\n", __FILE__); return -ENODEV; } - r = gpio_direction_output(phy->gpio_ena, 1); - - if (r) { - pr_err("%s : ena gpio_direction_output failed\n", - __FILE__); - return -ENODEV; - } } /* IRQ */ -- cgit v1.2.3 From 6ae3ed1c52b9ce12e1b3d2ac8f648b7de1569dfe Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:30 +0200 Subject: NFC: st21nfca: Fix sparse: cast to restricted __be32 Fixing "sparse: cast to restricted __be32" message when building with make C=1 CF=-D__CHECK_ENDIAN__ Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index a902b0551c86..823be16b2510 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -355,8 +355,8 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, if (r < 0) return r; - pol_req = - be32_to_cpu(ST21NFCA_RF_READER_F_POL_REQ_DEFAULT); + pol_req = be32_to_cpu((__force __be32) + ST21NFCA_RF_READER_F_POL_REQ_DEFAULT); r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE, ST21NFCA_RF_READER_F_POL_REQ, (u8 *) &pol_req, 4); -- cgit v1.2.3 From 3e6df9191abe9dc46b7f9f540e1c3c73cfaccedf Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:31 +0200 Subject: NFC: st21nfca: Fix scripts/checkpatch.pl warnings "Missing a blank line after declarations" Fixing scripts/checkpatch.pl warning "Missing a blank line after declarations" in: - st21nfca.c: - check_presence after fwi variable declaration. - get_frame_size after len variable declaration. - st21nfca_hci_i2c_repack after "i, j, r, size" variable declaration. - st21nfca_dep.c st21nfca_tx_work after skb pointer declaration. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/i2c.c | 2 ++ drivers/nfc/st21nfca/st21nfca.c | 1 + drivers/nfc/st21nfca/st21nfca_dep.c | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index d7a2c7636e26..72ad36873bdf 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -271,6 +271,7 @@ static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb) static int get_frame_size(u8 *buf, int buflen) { int len = 0; + if (buf[len + 1] == ST21NFCA_SOF_EOF) return 0; @@ -311,6 +312,7 @@ static int check_crc(u8 *buf, int buflen) static int st21nfca_hci_i2c_repack(struct sk_buff *skb) { int i, j, r, size; + if (skb->len < 1 || (skb->len > 1 && skb->data[1] != 0)) return -EBADMSG; diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index 823be16b2510..b6ad8c902f8d 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -790,6 +790,7 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, struct nfc_target *target) { u8 fwi = 0x11; + switch (target->hci_reader_gate) { case NFC_HCI_RF_READER_A_GATE: case NFC_HCI_RF_READER_B_GATE: diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index b2d9957b57f8..a62b6485cbbe 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -121,6 +121,7 @@ static void st21nfca_tx_work(struct work_struct *work) struct nfc_dev *dev; struct sk_buff *skb; + if (info) { dev = info->hdev->ndev; skb = info->dep_info.tx_pending; -- cgit v1.2.3 From 361325e21d3a06a31ab53baf452c0946743b7abb Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:32 +0200 Subject: NFC: st21nfcb: Fix scripts/checkpatch.pl error "code indent should use tabs where possible" Fixing scripts/checkpatch.pl error "code indent should use tabs where possible" in: - i2c.c in st21nfcb_nci_irq_thread_fn function. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 8af880ead5db..5a166cde35bc 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -235,7 +235,7 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id) r = st21nfcb_nci_i2c_read(phy, &skb); if (r == -EREMOTEIO) { phy->hard_fault = r; - ndlc_recv(phy->ndlc, NULL); + ndlc_recv(phy->ndlc, NULL); return IRQ_HANDLED; } else if (r == -ENOMEM || r == -EBADMSG) { return IRQ_HANDLED; -- cgit v1.2.3 From 56ee645e304c9b86b48768de8e52babd5b6e1d8a Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:33 +0200 Subject: NFC: st21nfcb: Convert to use devm_gpio_request_one Simplify the code a bit as mention by Axel Lin in a previous patch for st21nfca. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 5a166cde35bc..7ae9767dbcce 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -273,18 +273,12 @@ static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client) } /* GPIO request and configuration */ - r = devm_gpio_request(&client->dev, gpio, "clf_reset"); + r = devm_gpio_request_one(&client->dev, gpio, + GPIOF_OUT_INIT_HIGH, "clf_reset"); if (r) { nfc_err(&client->dev, "Failed to request reset pin\n"); return -ENODEV; } - - r = gpio_direction_output(gpio, 1); - if (r) { - nfc_err(&client->dev, - "Failed to set reset pin direction as output\n"); - return -ENODEV; - } phy->gpio_reset = gpio; /* IRQ */ @@ -325,32 +319,20 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client) phy->gpio_reset = pdata->gpio_reset; phy->irq_polarity = pdata->irq_polarity; - r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up"); + r = devm_gpio_request_one(&client->dev, phy->gpio_irq, + GPIOF_IN, "clf_irq"); if (r) { pr_err("%s : gpio_request failed\n", __FILE__); return -ENODEV; } - r = gpio_direction_input(phy->gpio_irq); - if (r) { - pr_err("%s : gpio_direction_input failed\n", __FILE__); - return -ENODEV; - } - - r = devm_gpio_request(&client->dev, - phy->gpio_reset, "clf_reset"); + r = devm_gpio_request_one(&client->dev, + phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset"); if (r) { pr_err("%s : reset gpio_request failed\n", __FILE__); return -ENODEV; } - r = gpio_direction_output(phy->gpio_reset, 1); - if (r) { - pr_err("%s : reset gpio_direction_output failed\n", - __FILE__); - return -ENODEV; - } - /* IRQ */ irq = gpio_to_irq(phy->gpio_irq); if (irq < 0) { -- cgit v1.2.3 From d363d7d0a5755b347de42c28aeab23ecfdcd2348 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:34 +0200 Subject: NFC: st21nfcb: Remove double assignment of .owner in struct device_driver The .owner member of struct device_driver is assigned THIS_MODULE twice. Introduced by: commit 35630df68d6030daf12dde12ed07bbe26324e6ac NFC: st21nfcb: Add driver for STMicroelectronics ST21NFCB NFC chip Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 7ae9767dbcce..11bd5f7220ac 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -430,7 +430,6 @@ static struct i2c_driver st21nfcb_nci_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = ST21NFCB_NCI_I2C_DRIVER_NAME, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_st21nfcb_i2c_match), }, .probe = st21nfcb_nci_i2c_probe, -- cgit v1.2.3 From 2c376a9e3c973e7923daba78aa16c768503cdef3 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:35 +0200 Subject: NFC: st21nfcb: Remove useless new line in nfc_err call Remove a uselss new line in nfc_err call. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 11bd5f7220ac..ff67bbf53011 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -284,8 +284,7 @@ static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client) /* IRQ */ r = irq_of_parse_and_map(pp, 0); if (r < 0) { - nfc_err(&client->dev, - "Unable to get irq, error: %d\n", r); + nfc_err(&client->dev, "Unable to get irq, error: %d\n", r); return r; } -- cgit v1.2.3 From df2566fe37d92dfba032e6084ebfb708dac5dc9a Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:36 +0200 Subject: NFC: st21nfcb: Remove inappropriate kfree on a previously devm_kzalloc pointer In case of an error during driver probe, info pointer was freed with kfree. No need to free anything when using devm_kzalloc. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/st21nfcb.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c index 4d95863e3063..64d2eaf40ef8 100644 --- a/drivers/nfc/st21nfcb/st21nfcb.c +++ b/drivers/nfc/st21nfcb/st21nfcb.c @@ -94,23 +94,18 @@ int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom, phy_headroom, phy_tailroom); if (!ndlc->ndev) { pr_err("Cannot allocate nfc ndev\n"); - r = -ENOMEM; - goto err_alloc_ndev; + return -ENOMEM; } info->ndlc = ndlc; nci_set_drvdata(ndlc->ndev, info); r = nci_register_device(ndlc->ndev); - if (r) - goto err_regdev; - - return r; -err_regdev: - nci_free_device(ndlc->ndev); + if (r) { + pr_err("Cannot register nfc device to nci core\n"); + nci_free_device(ndlc->ndev); + } -err_alloc_ndev: - kfree(info); return r; } EXPORT_SYMBOL_GPL(st21nfcb_nci_probe); -- cgit v1.2.3 From 9ec1f58b9a8ecd72e675c33bfe8ceaf1bc0dc4c5 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:37 +0200 Subject: NFC: st21nfca: Fix logic when setting session_id If dev_num >= ST21NFCA_NUM_DEVICES, the driver was returning an incorrect success return code. Once dev_num is set, it was not stated as busy. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index b6ad8c902f8d..438e06e6eb6a 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -905,8 +905,11 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, * persistent info to discriminate 2 identical chips */ dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES); + if (dev_num >= ST21NFCA_NUM_DEVICES) - goto err_alloc_hdev; + return -ENODEV; + + set_bit(dev_num, dev_mask); scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x", "ST21AH", dev_num); -- cgit v1.2.3 From 06ed3d607b1030365e6f4bdae193e64378e4264b Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 28 Jul 2014 18:11:38 +0200 Subject: NFC: st21nfca: Remove useless new line in nfc_err call Remove a useless new line in nfc_err call. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index 72ad36873bdf..0ea756b77519 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -539,8 +539,7 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) /* IRQ */ r = irq_of_parse_and_map(pp, 0); if (r < 0) { - nfc_err(&client->dev, - "Unable to get irq, error: %d\n", r); + nfc_err(&client->dev, "Unable to get irq, error: %d\n", r); return r; } -- cgit v1.2.3 From 72030a2eeb182575f1bf2383f1e9267d4a6ece61 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 11 Aug 2014 00:04:52 +0200 Subject: NFC: st21nfca: Change nfcid3 generation nfcid3 is based on sensf_res value. target->sensf is never NULL as it is a table. Check the sensf_res_len instead to make sure sensf_res is set or not. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index a62b6485cbbe..cd942c5adc53 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -523,7 +523,7 @@ int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len) memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE); target = hdev->ndev->targets; - if (target->sensf_res) + if (target->sensf_res_len > 0) memcpy(atr_req->nfcid3, target->sensf_res, target->sensf_res_len); else -- cgit v1.2.3 From 32b41d8f7587b6e8a2cbb3a15f83c3a9687f1f17 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 11 Aug 2014 00:04:53 +0200 Subject: NFC: st21nfca: Remove useless err == 0 condition On top of st21nfca_im_recv_atr_res_cb and st21nfca_im_recv_dep_res_cb a condition if (err != 0) is present. Because err is never modified in the code err will always be 0 at the end. The condition can be removed. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index cd942c5adc53..979c96986b34 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -485,8 +485,7 @@ static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb, ST21NFCA_PP2LRI(atr_res->ppi)); break; default: - if (err == 0) - kfree_skb(skb); + kfree_skb(skb); break; } } @@ -616,8 +615,7 @@ static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, } exit: - if (err == 0) - kfree_skb(skb); + kfree_skb(skb); } int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb) -- cgit v1.2.3 From a51577c9e3c49dbc44c821f9e170b96bbea716e3 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 11 Aug 2014 00:04:54 +0200 Subject: NFC: st21nfca: Remove useless IS_ERR(skb) conditions skb is already verified to be not null from the below hci layer. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index 979c96986b34..b6de27b5011d 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -198,10 +198,6 @@ static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, int r; skb_trim(skb, skb->len - 1); - if (IS_ERR(skb)) { - r = PTR_ERR(skb); - goto exit; - } if (!skb->len) { r = -EIO; @@ -281,11 +277,6 @@ static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev, int r; skb_trim(skb, skb->len - 1); - if (IS_ERR(skb)) { - r = PTR_ERR(skb); - skb = NULL; - goto exit; - } if (!skb->len) { r = -EIO; @@ -331,11 +322,6 @@ static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); skb_trim(skb, skb->len - 1); - if (IS_ERR(skb)) { - r = PTR_ERR(skb); - skb = NULL; - goto exit; - } size = 4; @@ -369,12 +355,6 @@ static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, break; } - if (IS_ERR(skb)) { - r = PTR_ERR(skb); - skb = NULL; - goto exit; - } - skb_pull(skb, size); return nfc_tm_data_received(hdev->ndev, skb); -- cgit v1.2.3 From 56f1ffcccd784672654918f9214979b4918c2544 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Mon, 11 Aug 2014 00:04:56 +0200 Subject: NFC: st21nfca: Add condition to make sure atr_req->length is valid. gb_len in st21nfca_tm_send_atr_res can be negative. Not checking for that could lead to a potential kernel oops. We now make sure that atr_req->length > sizeof(struct st21nfca_atr_req) to avoid such situation. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index b6de27b5011d..6c09a66d9a1d 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -211,6 +211,11 @@ static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, atr_req = (struct st21nfca_atr_req *)skb->data; + if (atr_req->length < sizeof(struct st21nfca_atr_req)) { + r = -EPROTO; + goto exit; + } + r = st21nfca_tm_send_atr_res(hdev, atr_req); if (r) goto exit; -- cgit v1.2.3 From ac633ba6acb94a11b09a7ec417c72f65c6308b7a Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Wed, 3 Sep 2014 23:30:26 +0200 Subject: NFC: st21nfcb: Fix logic when running into i2c read retry When retrying to read the NCI header, the CLF might not be available the first time. However it may not be successful the second time and this may cause an error in the function. Enforce the retrieve data length is as expected. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index ff67bbf53011..02fac319dfa9 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -168,7 +168,9 @@ static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy, if (r == -EREMOTEIO) { /* Retry, chip was in standby */ usleep_range(1000, 4000); r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE); - } else if (r != ST21NFCB_NCI_I2C_MIN_SIZE) { + } + + if (r != ST21NFCB_NCI_I2C_MIN_SIZE) { nfc_err(&client->dev, "cannot read ndlc & nci header\n"); return -EREMOTEIO; } -- cgit v1.2.3 From cebe22244206d51b80c778f09304d21198652f71 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Wed, 3 Sep 2014 23:30:28 +0200 Subject: NFC: st21nfca: Clean up st21nfca.h macros Clean up st21nfca.h macros and move the one only used in st21nfca.c. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca.c | 21 +++++++++++++++++++++ drivers/nfc/st21nfca/st21nfca.h | 21 --------------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index 438e06e6eb6a..bff657524b18 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -45,6 +45,23 @@ #define ST21NFCA_RF_READER_14443_3_A_ATQA 0x03 #define ST21NFCA_RF_READER_14443_3_A_SAK 0x04 +#define ST21NFCA_RF_READER_F_DATARATE 0x01 +#define ST21NFCA_RF_READER_F_DATARATE_106 0x01 +#define ST21NFCA_RF_READER_F_DATARATE_212 0x02 +#define ST21NFCA_RF_READER_F_DATARATE_424 0x04 +#define ST21NFCA_RF_READER_F_POL_REQ 0x02 +#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000 +#define ST21NFCA_RF_READER_F_NFCID2 0x03 +#define ST21NFCA_RF_READER_F_NFCID1 0x04 + +#define ST21NFCA_RF_CARD_F_MODE 0x01 +#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04 +#define ST21NFCA_RF_CARD_F_NFCID1 0x05 +#define ST21NFCA_RF_CARD_F_SENS_RES 0x06 +#define ST21NFCA_RF_CARD_F_SEL_RES 0x07 +#define ST21NFCA_RF_CARD_F_DATARATE 0x08 +#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 + #define ST21NFCA_DEVICE_MGNT_GATE 0x01 #define ST21NFCA_DEVICE_MGNT_PIPE 0x02 @@ -60,6 +77,10 @@ ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) #define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ +#define ST21NFCA_EVT_FIELD_ON 0x11 +#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 +#define ST21NFCA_EVT_CARD_ACTIVATED 0x13 +#define ST21NFCA_EVT_FIELD_OFF 0x14 static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h index 96fe5a62dc0d..a0b77f1ba6d9 100644 --- a/drivers/nfc/st21nfca/st21nfca.h +++ b/drivers/nfc/st21nfca/st21nfca.h @@ -82,30 +82,9 @@ struct st21nfca_hci_info { #define ST21NFCA_WR_XCHG_DATA 0x10 #define ST21NFCA_RF_READER_F_GATE 0x14 -#define ST21NFCA_RF_READER_F_DATARATE 0x01 -#define ST21NFCA_RF_READER_F_DATARATE_106 0x01 -#define ST21NFCA_RF_READER_F_DATARATE_212 0x02 -#define ST21NFCA_RF_READER_F_DATARATE_424 0x04 -#define ST21NFCA_RF_READER_F_POL_REQ 0x02 -#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000 -#define ST21NFCA_RF_READER_F_NFCID2 0x03 -#define ST21NFCA_RF_READER_F_NFCID1 0x04 -#define ST21NFCA_RF_READER_F_SENS_RES 0x05 #define ST21NFCA_RF_CARD_F_GATE 0x24 -#define ST21NFCA_RF_CARD_F_MODE 0x01 -#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04 -#define ST21NFCA_RF_CARD_F_NFCID1 0x05 -#define ST21NFCA_RF_CARD_F_SENS_RES 0x06 -#define ST21NFCA_RF_CARD_F_SEL_RES 0x07 -#define ST21NFCA_RF_CARD_F_DATARATE 0x08 -#define ST21NFCA_RF_CARD_F_DATARATE_106 0x00 -#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 #define ST21NFCA_EVT_SEND_DATA 0x10 -#define ST21NFCA_EVT_FIELD_ON 0x11 -#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 -#define ST21NFCA_EVT_CARD_ACTIVATED 0x13 -#define ST21NFCA_EVT_FIELD_OFF 0x14 #endif /* __LOCAL_ST21NFCA_H_ */ -- cgit v1.2.3 From efaf956ad6852a7ae0cc4c78bd31079f8039daa6 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Wed, 3 Sep 2014 23:30:29 +0200 Subject: NFC: st21nfca: Clean up macros alignment Align every macros on the same column. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca.c | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index bff657524b18..fcb2955f8e8d 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -34,7 +34,7 @@ #define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x30 #define ST21NFCA_RF_READER_ISO15693_GATE 0x12 -#define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01 +#define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01 /* * Reader gate for communication with contact-less cards using Type A @@ -45,38 +45,38 @@ #define ST21NFCA_RF_READER_14443_3_A_ATQA 0x03 #define ST21NFCA_RF_READER_14443_3_A_SAK 0x04 -#define ST21NFCA_RF_READER_F_DATARATE 0x01 -#define ST21NFCA_RF_READER_F_DATARATE_106 0x01 -#define ST21NFCA_RF_READER_F_DATARATE_212 0x02 -#define ST21NFCA_RF_READER_F_DATARATE_424 0x04 -#define ST21NFCA_RF_READER_F_POL_REQ 0x02 -#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000 -#define ST21NFCA_RF_READER_F_NFCID2 0x03 -#define ST21NFCA_RF_READER_F_NFCID1 0x04 - -#define ST21NFCA_RF_CARD_F_MODE 0x01 -#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04 -#define ST21NFCA_RF_CARD_F_NFCID1 0x05 -#define ST21NFCA_RF_CARD_F_SENS_RES 0x06 -#define ST21NFCA_RF_CARD_F_SEL_RES 0x07 -#define ST21NFCA_RF_CARD_F_DATARATE 0x08 -#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 +#define ST21NFCA_RF_READER_F_DATARATE 0x01 +#define ST21NFCA_RF_READER_F_DATARATE_106 0x01 +#define ST21NFCA_RF_READER_F_DATARATE_212 0x02 +#define ST21NFCA_RF_READER_F_DATARATE_424 0x04 +#define ST21NFCA_RF_READER_F_POL_REQ 0x02 +#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000 +#define ST21NFCA_RF_READER_F_NFCID2 0x03 +#define ST21NFCA_RF_READER_F_NFCID1 0x04 + +#define ST21NFCA_RF_CARD_F_MODE 0x01 +#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04 +#define ST21NFCA_RF_CARD_F_NFCID1 0x05 +#define ST21NFCA_RF_CARD_F_SENS_RES 0x06 +#define ST21NFCA_RF_CARD_F_SEL_RES 0x07 +#define ST21NFCA_RF_CARD_F_DATARATE 0x08 +#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 #define ST21NFCA_DEVICE_MGNT_GATE 0x01 #define ST21NFCA_DEVICE_MGNT_PIPE 0x02 -#define ST21NFCA_DM_GETINFO 0x13 -#define ST21NFCA_DM_GETINFO_PIPE_LIST 0x02 -#define ST21NFCA_DM_GETINFO_PIPE_INFO 0x01 -#define ST21NFCA_DM_PIPE_CREATED 0x02 -#define ST21NFCA_DM_PIPE_OPEN 0x04 -#define ST21NFCA_DM_RF_ACTIVE 0x80 -#define ST21NFCA_DM_DISCONNECT 0x30 +#define ST21NFCA_DM_GETINFO 0x13 +#define ST21NFCA_DM_GETINFO_PIPE_LIST 0x02 +#define ST21NFCA_DM_GETINFO_PIPE_INFO 0x01 +#define ST21NFCA_DM_PIPE_CREATED 0x02 +#define ST21NFCA_DM_PIPE_OPEN 0x04 +#define ST21NFCA_DM_RF_ACTIVE 0x80 +#define ST21NFCA_DM_DISCONNECT 0x30 #define ST21NFCA_DM_IS_PIPE_OPEN(p) \ ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) -#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ +#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ #define ST21NFCA_EVT_FIELD_ON 0x11 #define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 #define ST21NFCA_EVT_CARD_ACTIVATED 0x13 -- cgit v1.2.3 From 0a91e8ac240a12ac3a03581deb8cd531788c63d4 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Wed, 3 Sep 2014 23:30:30 +0200 Subject: NFC: st21nfca: fix "WARNING: else is not generally useful after a break or return" scripts/checkpatch.pl -f drivers/nfc/st21nfca.c is throwing the following: WARNING: else is not generally useful after a break or return #866: FILE: drivers/nfc/st21nfca/st21nfca.c:866: + return 0; + } else { Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index fcb2955f8e8d..e5f92aaa5466 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -862,7 +862,6 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, r = st21nfca_tm_event_send_data(hdev, skb, gate); if (r < 0) goto exit; - return 0; } else { info->dep_info.curr_nfc_dep_pni = 0; return 1; -- cgit v1.2.3 From 890c165261f92e23005d84762acc98892acaa504 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Wed, 3 Sep 2014 23:30:32 +0200 Subject: NFC: st21nfcb: Remove useless headers Remove some headers as they are: - not relevent for st21nfcb. - called multiple times for no reason: example st21nfcb.h already include ndlc.h. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 8 -------- drivers/nfc/st21nfcb/st21nfcb.c | 1 - drivers/nfc/st21nfcb/st21nfcb.h | 2 -- 3 files changed, 11 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 02fac319dfa9..83423462663d 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -17,24 +17,16 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include #include #include -#include #include #include #include -#include -#include #include -#include -#include -#include - #include "ndlc.h" #define DRIVER_DESC "NCI NFC driver for ST21NFCB" diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c index 64d2eaf40ef8..90d37156169e 100644 --- a/drivers/nfc/st21nfcb/st21nfcb.c +++ b/drivers/nfc/st21nfcb/st21nfcb.c @@ -22,7 +22,6 @@ #include #include "st21nfcb.h" -#include "ndlc.h" #define DRIVER_DESC "NCI NFC driver for ST21NFCB" diff --git a/drivers/nfc/st21nfcb/st21nfcb.h b/drivers/nfc/st21nfcb/st21nfcb.h index 4bbbebb9f34d..ea58a56ad794 100644 --- a/drivers/nfc/st21nfcb/st21nfcb.h +++ b/drivers/nfc/st21nfcb/st21nfcb.h @@ -19,8 +19,6 @@ #ifndef __LOCAL_ST21NFCB_H_ #define __LOCAL_ST21NFCB_H_ -#include - #include "ndlc.h" /* Define private flags: */ -- cgit v1.2.3 From 671970f531378e2a22ba0168d85dfca1f4e082c4 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 23 Sep 2014 11:25:45 -0700 Subject: NFC: trf7970a: Remove useless local variable The trf7970a_suspend() routine always returns zero so don't use a local return variable to hold the return value. This fixes up a smatch warning. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 2a521bb38060..00149a9a50ef 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -2123,7 +2123,6 @@ static int trf7970a_suspend(struct device *dev) { struct spi_device *spi = container_of(dev, struct spi_device, dev); struct trf7970a *trf = spi_get_drvdata(spi); - int ret = 0; dev_dbg(dev, "Suspend\n"); @@ -2133,7 +2132,7 @@ static int trf7970a_suspend(struct device *dev) mutex_unlock(&trf->lock); - return ret; + return 0; } static int trf7970a_resume(struct device *dev) -- cgit v1.2.3 From 55ef2e75ccf0d91f7b2f4251dc3b9e56df840928 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 23 Sep 2014 11:25:46 -0700 Subject: NFC: trf7970a: Remove unnecessary local variable initialization There is no need to initialize the 'ret' variable in trf7970a_resume(). Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 00149a9a50ef..59a7df7f023c 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -2139,7 +2139,7 @@ static int trf7970a_resume(struct device *dev) { struct spi_device *spi = container_of(dev, struct spi_device, dev); struct trf7970a *trf = spi_get_drvdata(spi); - int ret = 0; + int ret; dev_dbg(dev, "Resume\n"); -- cgit v1.2.3 From b9e3016a5369839bf923c8d2bec9d1552e50f3f3 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 23 Sep 2014 11:25:47 -0700 Subject: NFC: trf7970a: Unlock mutex before exiting trf7970a_irq() Recent changes to trf7970a_irq() added a couple return paths that don't unlock the mutex that is locked when the routine is entered. Fix this by ensuring the mutex is always unlocked before returning. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 59a7df7f023c..0fe7b957436c 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -920,7 +920,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) TRF7970A_SPECIAL_FCN_REG1, TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL); if (ret) - return ret; + goto err_unlock_exit; trf->special_fcn_reg1 = TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL; @@ -933,7 +933,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); if (ret) - return ret; + goto err_unlock_exit; trf->iso_ctrl = iso_ctrl; } @@ -975,6 +975,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) __func__, trf->state); } +err_unlock_exit: mutex_unlock(&trf->lock); return IRQ_HANDLED; } -- cgit v1.2.3 From fc0ae24386142299db14dfea7f32a20022d94d90 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Tue, 23 Sep 2014 11:25:48 -0700 Subject: NFC: trf7970a: Unlock mutex before exiting _trf7970a_tg_listen() The recently added _trf7970a_tg_listen() routine has some return paths that don't unlock the mutex that is locked when the routine is entered. Fix this by always unlocking the mutex before returning. Signed-off-by: Mark A. Greer Signed-off-by: Samuel Ortiz --- drivers/nfc/trf7970a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 0fe7b957436c..d2ccd2890647 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1728,22 +1728,22 @@ static int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, TRF7970A_RX_SPECIAL_SETTINGS_C424 | TRF7970A_RX_SPECIAL_SETTINGS_C212); if (ret) - return ret; + goto out_err; ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL, TRF7970A_REG_IO_CTRL_VRS(0x1)); if (ret) - return ret; + goto out_err; ret = trf7970a_write(trf, TRF7970A_NFC_LOW_FIELD_LEVEL, TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(0x3)); if (ret) - return ret; + goto out_err; ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, TRF7970A_NFC_TARGET_LEVEL_RFDET(0x7)); if (ret) - return ret; + goto out_err; trf->ddev = ddev; trf->cb = cb; -- cgit v1.2.3 From cc3faac9d88faebe59556f3754ad306117e53b72 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:43 +0200 Subject: NFC: st21nfca: Fix few coding style issue Fix few conding style issue such as useless line return or tab. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index 6c09a66d9a1d..03dacc6550bc 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -129,9 +129,8 @@ static void st21nfca_tx_work(struct work_struct *work) device_lock(&dev->dev); nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE, - ST21NFCA_WR_XCHG_DATA, - skb->data, skb->len, - info->async_cb, info); + ST21NFCA_WR_XCHG_DATA, skb->data, skb->len, + info->async_cb, info); device_unlock(&dev->dev); kfree_skb(skb); } @@ -239,7 +238,6 @@ static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, struct st21nfca_psl_res *psl_res; struct sk_buff *skb; u8 bitrate[2] = {0, 0}; - int r; skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL); @@ -311,7 +309,7 @@ int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb) *skb_push(skb, 1) = skb->len; r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, - ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); + ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); kfree_skb(skb); return r; -- cgit v1.2.3 From ecc6522b0804d8102d57a9eac36448bda416ce8c Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:44 +0200 Subject: NFC: st21nfca: Fix potential skb leaks in NFC-DEP code After a unsuccessful call to nfc_hci_send_event the skb was not freed and might lead to memory leak. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index 03dacc6550bc..bf3132ba743c 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -185,8 +185,10 @@ static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev, info->dep_info.curr_nfc_dep_pni = 0; - return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, + r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); + kfree_skb(skb); + return r; } static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, @@ -254,6 +256,8 @@ static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); + if (r < 0) + goto error; /* * ST21NFCA only support P2P passive. @@ -269,8 +273,11 @@ static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, } /* Send an event to change bitrate change event to card f */ - return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, + r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2); +error: + kfree_skb(skb); + return r; } static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev, -- cgit v1.2.3 From 90d5f81afc8369774a6c581b600aef80b1448d35 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:45 +0200 Subject: NFC: st21nfca: Fix recursive fault when doing p2p in target mode. This patch fix a previous patch introduce by commit 0a91e8ac240a12ac3a03581deb8cd531788c63d4 It is actually fixing a double free mistake in all st21nfca_tm_* function. We decide to return directly in case of successful execution because skb got already freed. In st21nfca_tm_recv_dep_req it got freed by nfc_tm_data_received. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index e5f92aaa5466..a89e56c2c749 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c @@ -861,19 +861,16 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, if (gate == ST21NFCA_RF_CARD_F_GATE) { r = st21nfca_tm_event_send_data(hdev, skb, gate); if (r < 0) - goto exit; - } else { - info->dep_info.curr_nfc_dep_pni = 0; - return 1; + return r; + return 0; } - break; + info->dep_info.curr_nfc_dep_pni = 0; + return 1; default: return 1; } kfree_skb(skb); return 0; -exit: - return r; } static struct nfc_hci_ops st21nfca_hci_ops = { -- cgit v1.2.3 From 4294e32040b5142824f420d4a3ae604b92f1d1b5 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:47 +0200 Subject: NFC: st21nfcb: Fix improper management of -EREMOTEIO error code. On st21nfcb the irq line might be kept to active state because of other interfaces activity. This may generate i2c read tentative resulting in i2c NACK. This fix will currently let NDLC upper layer to decide when it is relevent to signal to the physical layer when the chip as muted. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 19 ++++--------------- drivers/nfc/st21nfcb/ndlc.h | 4 ++++ 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 83423462663d..0b8f72176de0 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -55,12 +55,6 @@ struct st21nfcb_i2c_phy { unsigned int irq_polarity; int powered; - - /* - * < 0 if hardware error occured (e.g. i2c err) - * and prevents normal operation. - */ - int hard_fault; }; #define I2C_DUMP_SKB(info, skb) \ @@ -114,8 +108,8 @@ static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb) I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb); - if (phy->hard_fault != 0) - return phy->hard_fault; + if (phy->ndlc->hard_fault != 0) + return phy->ndlc->hard_fault; r = i2c_master_send(client, skb->data, skb->len); if (r == -EREMOTEIO) { /* Retry, chip was in standby */ @@ -218,7 +212,7 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id) client = phy->i2c_dev; dev_dbg(&client->dev, "IRQ\n"); - if (phy->hard_fault) + if (phy->ndlc->hard_fault) return IRQ_HANDLED; if (!phy->powered) { @@ -227,13 +221,8 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id) } r = st21nfcb_nci_i2c_read(phy, &skb); - if (r == -EREMOTEIO) { - phy->hard_fault = r; - ndlc_recv(phy->ndlc, NULL); - return IRQ_HANDLED; - } else if (r == -ENOMEM || r == -EBADMSG) { + if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG) return IRQ_HANDLED; - } ndlc_recv(phy->ndlc, skb); diff --git a/drivers/nfc/st21nfcb/ndlc.h b/drivers/nfc/st21nfcb/ndlc.h index c30a2f0faa5f..b28140e0cd78 100644 --- a/drivers/nfc/st21nfcb/ndlc.h +++ b/drivers/nfc/st21nfcb/ndlc.h @@ -42,6 +42,10 @@ struct llt_ndlc { struct device *dev; + /* + * < 0 if hardware error occured + * and prevents normal operation. + */ int hard_fault; }; -- cgit v1.2.3 From fa0daa02fb063ecef39b7d421c3d9c4109381dc2 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:48 +0200 Subject: NFC: st21nfcb: Fix improper ndlc T2 management T2 was never started when sending a command. Start it when sending a command for the first attempt and stop it once we receive the answer. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/ndlc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c index 83c97c36112b..e7bff8921d11 100644 --- a/drivers/nfc/st21nfcb/ndlc.c +++ b/drivers/nfc/st21nfcb/ndlc.c @@ -112,6 +112,10 @@ static void llt_ndlc_send_queue(struct llt_ndlc *ndlc) ndlc->t1_active = true; mod_timer(&ndlc->t1_timer, time_sent + msecs_to_jiffies(NDLC_TIMER_T1)); + /* start timer t2 for chip availability */ + ndlc->t2_active = true; + mod_timer(&ndlc->t2_timer, time_sent + + msecs_to_jiffies(NDLC_TIMER_T2)); } } @@ -207,7 +211,7 @@ static void llt_ndlc_sm_work(struct work_struct *work) ndlc->t2_active = false; ndlc->t1_active = false; del_timer_sync(&ndlc->t1_timer); - + del_timer_sync(&ndlc->t2_timer); ndlc_close(ndlc); ndlc->hard_fault = -EREMOTEIO; } -- cgit v1.2.3 From 9e87f9a9c4c4754508b2c2638fbde9e10c7a103b Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:49 +0200 Subject: NFC: nci: Add support for proprietary RF Protocols In NFC Forum NCI specification, some RF Protocol values are reserved for proprietary use (from 0x80 to 0xfe). Some CLF vendor may need to use one value within this range for specific technology. Furthermore, some CLF may not becompliant with NFC Froum NCI specification 2.0 and therefore will not support RF Protocol value 0x06 for PROTOCOL_T5T as mention in a draft specification and in a recent push. Adding get_rf_protocol handle to the nci_ops structure will help to set the correct technology to target. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/st21nfcb.c | 10 ++++++++++ include/net/nfc/nci_core.h | 9 +++++---- net/nfc/nci/ntf.c | 9 ++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c index 90d37156169e..e72dae816e72 100644 --- a/drivers/nfc/st21nfcb/st21nfcb.c +++ b/drivers/nfc/st21nfcb/st21nfcb.c @@ -25,6 +25,8 @@ #define DRIVER_DESC "NCI NFC driver for ST21NFCB" +#define ST21NFCB_NCI1_X_PROPRIETARY_ISO15693 0x83 + static int st21nfcb_nci_open(struct nci_dev *ndev) { struct st21nfcb_nci_info *info = nci_get_drvdata(ndev); @@ -64,10 +66,18 @@ static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb) return ndlc_send(info->ndlc, skb); } +static __u32 st21nfcb_nci_get_rfprotocol(struct nci_dev *ndev, + __u8 rf_protocol) +{ + return rf_protocol == ST21NFCB_NCI1_X_PROPRIETARY_ISO15693 ? + NFC_PROTO_ISO15693_MASK : 0; +} + static struct nci_ops st21nfcb_nci_ops = { .open = st21nfcb_nci_open, .close = st21nfcb_nci_close, .send = st21nfcb_nci_send, + .get_rfprotocol = st21nfcb_nci_get_rfprotocol, }; int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom, diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 1f9a0f5272fe..75d10e625c49 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -64,10 +64,11 @@ enum nci_state { struct nci_dev; struct nci_ops { - int (*open)(struct nci_dev *ndev); - int (*close)(struct nci_dev *ndev); - int (*send)(struct nci_dev *ndev, struct sk_buff *skb); - int (*setup)(struct nci_dev *ndev); + int (*open)(struct nci_dev *ndev); + int (*close)(struct nci_dev *ndev); + int (*send)(struct nci_dev *ndev, struct sk_buff *skb); + int (*setup)(struct nci_dev *ndev); + __u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol); }; #define NCI_MAX_SUPPORTED_RF_INTERFACES 4 diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 25e44cebd60a..205b35f666db 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c @@ -167,6 +167,13 @@ static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev, return data; } +__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol) +{ + if (ndev->ops->get_rfprotocol) + return ndev->ops->get_rfprotocol(ndev, rf_protocol); + return 0; +} + static int nci_add_new_protocol(struct nci_dev *ndev, struct nfc_target *target, __u8 rf_protocol, @@ -195,7 +202,7 @@ static int nci_add_new_protocol(struct nci_dev *ndev, else if (rf_protocol == NCI_RF_PROTOCOL_T5T) protocol = NFC_PROTO_ISO15693_MASK; else - protocol = 0; + protocol = nci_get_prop_rf_protocol(ndev, rf_protocol); if (!(protocol & ndev->poll_prots)) { pr_err("the target found does not have the desired protocol\n"); -- cgit v1.2.3 From 941ec5c6b02a93710c397e69b50671949f3b9dd3 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:50 +0200 Subject: NFC: st21nfcb: Add ISO15693 Reader/Writer support Add support for ISO/IEC 15693 RF technology and Type 5 tags. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/st21nfcb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c index e72dae816e72..ea63d5877831 100644 --- a/drivers/nfc/st21nfcb/st21nfcb.c +++ b/drivers/nfc/st21nfcb/st21nfcb.c @@ -97,6 +97,7 @@ int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom, | NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK | NFC_PROTO_ISO14443_B_MASK + | NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK; ndlc->ndev = nci_allocate_device(&st21nfcb_nci_ops, protocols, -- cgit v1.2.3 From bc6b8275924b8af3d10ac35df0579d94fa169680 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:51 +0200 Subject: NFC: st21nfcb: remove error output In case we are not able to read out the NDLC/NCI header, we do not consider this as an issue and we will give a later chance. The NDLC layer will handle errors thanks to its internal timers. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfcb/i2c.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 0b8f72176de0..c5d2427a3db2 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c @@ -156,10 +156,8 @@ static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy, r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE); } - if (r != ST21NFCB_NCI_I2C_MIN_SIZE) { - nfc_err(&client->dev, "cannot read ndlc & nci header\n"); + if (r != ST21NFCB_NCI_I2C_MIN_SIZE) return -EREMOTEIO; - } len = be16_to_cpu(*(__be16 *) (buf + 2)); if (len > ST21NFCB_NCI_I2C_MAX_SIZE) { -- cgit v1.2.3 From 459e794b9b1e0c6be93745344c40364296e7aacd Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:52 +0200 Subject: NFC: st21nfca: ERR_PTR vs NULL fix "skb" can be NULL here but it can't be an ERR_PTR: - IS_ERR(NULL) return false and skb migth be NULL. - skb cannot be a ERR_PTR as nfc_hci_send_cmd_async it never using such cast. !skb is more appropriate at those places. Reported-by: Dan Carpenter Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index bf3132ba743c..9408122fb948 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -443,7 +443,7 @@ static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb, if (err != 0) return; - if (IS_ERR(skb)) + if (!skb) return; switch (info->async_cb_type) { @@ -555,7 +555,7 @@ static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, if (err != 0) return; - if (IS_ERR(skb)) + if (!skb) return; switch (info->async_cb_type) { -- cgit v1.2.3 From 094e93592433312548dd5e43d7b24b152f658063 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Sat, 13 Sep 2014 10:28:53 +0200 Subject: NFC: st21nfca: Fix potential double kfree_skb error skb is already freed in st21nfca_tx_work and was freed also in st21nfca_im_send_psl_req. Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st21nfca/st21nfca_dep.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/nfc') diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c index 9408122fb948..bfb6df56c505 100644 --- a/drivers/nfc/st21nfca/st21nfca_dep.c +++ b/drivers/nfc/st21nfca/st21nfca_dep.c @@ -428,8 +428,6 @@ static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi, *skb_push(skb, 1) = info->dep_info.to | 0x10; st21nfca_im_send_pdu(info, skb); - - kfree_skb(skb); } #define ST21NFCA_CB_TYPE_READER_F 1 -- cgit v1.2.3