/*
* TI TRF7970a RFID/NFC Transceiver Driver
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Erick Macias <emacias@ti.com>
* Author: Felipe Balbi <balbi@ti.com>
* Author: Mark A. Greer <mgreer@animalcreek.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/nfc.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <net/nfc/nfc.h>
#include <net/nfc/digital.h>
/* There are 3 ways the host can communicate with the trf7970a:
* parallel mode, SPI with Slave Select (SS) mode, and SPI without
* SS mode. The driver only supports the two SPI modes.
*
* 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.
*
* Timeouts are implemented using the delayed workqueue kernel facility.
* Timeouts are required so things don't hang when there is no response
* from the trf7970a (or tag). Using this mechanism creates a race with
* interrupts, however. That is, an interrupt and a timeout could occur
* closely enough together that one is blocked by the mutex while the other
* executes. When the timeout handler executes first and blocks the
* interrupt handler, it will eventually set the state to IDLE so the
* interrupt handler will check the state and exit with no harm done.
* When the interrupt handler executes first and blocks the timeout handler,
* the cancel_delayed_work() call will know that it didn't cancel the
* work item (i.e., timeout) and will return zero. That return code is
* used by the timer handler to indicate that it should ignore the timeout
* once its unblocked.
*
* Aborting an active command isn't as simple as it seems because the only
* 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()
* 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
* sending the data upstream, it frees the rx_skb and sends -ECANCELED
* upstream instead. If the command failed, that error will be sent