Commit 15ab90f4 authored by David S. Miller's avatar David S. Miller

Merge tag 'nfc-next-4.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next

Samuel Ortiz says:

====================
NFC 4.5 pull request

This is the first NFC pull request for 4.5 and it brings:

- A new driver for the STMicroelectronics ST95HF NFC chipset.
  The ST95HF is an NFC digital transceiver with an embedded analog
  front-end and as such relies on the Linux NFC digital
  implementation. This is the 3rd user of the NFC digital stack.

- ACPI support for the ST st-nci and st21nfca drivers.

- A small improvement for the nfcsim driver, as we can now tune
  the Rx delay through sysfs.

- A bunch of minor cleanups and small fixes from Christophe Ricard,
  for a few drivers and the NFC core code.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 197c949e c6dc65d8
* STMicroelectronics : NFC Transceiver ST95HF
ST NFC Transceiver is required to attach with SPI bus.
ST95HF node should be defined in DT as SPI slave device of SPI
master with which ST95HF transceiver is physically connected.
The properties defined below are required to be the part of DT
to include ST95HF transceiver into the platform.
Required properties:
===================
- reg: Address of SPI slave "ST95HF transceiver" on SPI master bus.
- compatible: should be "st,st95hf" for ST95HF NFC transceiver
- spi-max-frequency: Max. operating SPI frequency for ST95HF
transceiver.
- enable-gpio: GPIO line to enable ST95HF transceiver.
- interrupt-parent : Standard way to specify the controller to which
ST95HF transceiver's interrupt is routed.
- interrupts : Standard way to define ST95HF transceiver's out
interrupt.
Optional property:
=================
- st95hfvin-supply : This is an optional property. It contains a
phandle to ST95HF transceiver's regulator supply node in DT.
Example:
=======
spi@9840000 {
reg = <0x9840000 0x110>;
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&pio0 4>;
status = "okay";
st95hf@0{
reg = <0>;
compatible = "st,st95hf";
status = "okay";
spi-max-frequency = <1000000>;
enable-gpio = <&pio4 0>;
interrupt-parent = <&pio0>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
};
};
......@@ -7523,7 +7523,12 @@ F: net/nfc/
F: include/net/nfc/
F: include/uapi/linux/nfc.h
F: drivers/nfc/
F: include/linux/platform_data/microread.h
F: include/linux/platform_data/nfcmrvl.h
F: include/linux/platform_data/nxp-nci.h
F: include/linux/platform_data/pn544.h
F: include/linux/platform_data/st21nfca.h
F: include/linux/platform_data/st-nci.h
F: Documentation/devicetree/bindings/net/nfc/
NFS, SUNRPC, AND LOCKD CLIENTS
......
......@@ -76,4 +76,5 @@ source "drivers/nfc/st21nfca/Kconfig"
source "drivers/nfc/st-nci/Kconfig"
source "drivers/nfc/nxp-nci/Kconfig"
source "drivers/nfc/s3fwrn5/Kconfig"
source "drivers/nfc/st95hf/Kconfig"
endmenu
......@@ -16,3 +16,4 @@ obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
obj-$(CONFIG_NFC_ST_NCI) += st-nci/
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/
obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5/
obj-$(CONFIG_NFC_ST95HF) += st95hf/
......@@ -298,6 +298,12 @@ static int fdp_nci_i2c_probe(struct i2c_client *client,
return -ENODEV;
}
/* Checking if we have an irq */
if (client->irq <= 0) {
nfc_err(dev, "IRQ not present\n");
return -ENODEV;
}
phy = devm_kzalloc(dev, sizeof(struct fdp_i2c_phy),
GFP_KERNEL);
if (!phy)
......@@ -307,12 +313,6 @@ static int fdp_nci_i2c_probe(struct i2c_client *client,
phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;
i2c_set_clientdata(client, phy);
/* Checking if we have an irq */
if (client->irq <= 0) {
dev_err(dev, "IRQ not present\n");
return -ENODEV;
}
r = request_threaded_irq(client->irq, NULL, fdp_nci_i2c_irq_thread_fn,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
FDP_I2C_DRIVER_NAME, phy);
......
......@@ -50,8 +50,6 @@ struct microread_i2c_phy {
struct i2c_client *i2c_dev;
struct nfc_hci_dev *hdev;
int irq;
int hard_fault; /*
* < 0 if hardware error occured (e.g. i2c err)
* and prevents normal operation.
......
......@@ -32,6 +32,8 @@
#define NFCSIM_POLL_TARGET 2
#define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET)
#define RX_DEFAULT_DELAY 5
struct nfcsim {
struct nfc_dev *nfc_dev;
......@@ -51,6 +53,8 @@ struct nfcsim {
u8 initiator;
u32 rx_delay;
data_exchange_cb_t cb;
void *cb_context;
......@@ -320,10 +324,9 @@ static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target,
* If packet transmission occurs immediately between them, we have a
* non-stop flow of several tens of thousands SYMM packets per second
* and a burning cpu.
*
* TODO: Add support for a sysfs entry to control this delay.
*/
queue_delayed_work(wq, &peer->recv_work, msecs_to_jiffies(5));
queue_delayed_work(wq, &peer->recv_work,
msecs_to_jiffies(dev->rx_delay));
mutex_unlock(&peer->lock);
......@@ -461,6 +464,7 @@ static struct nfcsim *nfcsim_init_dev(void)
if (rc)
goto free_nfc_dev;
dev->rx_delay = RX_DEFAULT_DELAY;
return dev;
free_nfc_dev:
......
......@@ -52,7 +52,6 @@ struct nxp_nci_i2c_phy {
unsigned int gpio_en;
unsigned int gpio_fw;
unsigned int gpio_irq;
int hard_fault; /*
* < 0 if hardware error occurred (e.g. i2c err)
......@@ -85,7 +84,7 @@ static int nxp_nci_i2c_write(void *phy_id, struct sk_buff *skb)
return phy->hard_fault;
r = i2c_master_send(client, skb->data, skb->len);
if (r == -EREMOTEIO) {
if (r < 0) {
/* Retry, chip was in standby */
usleep_range(110000, 120000);
r = i2c_master_send(client, skb->data, skb->len);
......@@ -264,8 +263,6 @@ static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
return IRQ_NONE;
}
#ifdef CONFIG_OF
static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
{
struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client);
......@@ -294,48 +291,24 @@ static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
}
phy->gpio_fw = r;
r = irq_of_parse_and_map(pp, 0);
if (r < 0) {
nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
return r;
}
client->irq = r;
return 0;
}
#else
static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
{
return -ENODEV;
}
#endif
static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy)
{
struct i2c_client *client = phy->i2c_dev;
struct gpio_desc *gpiod_en, *gpiod_fw, *gpiod_irq;
struct gpio_desc *gpiod_en, *gpiod_fw;
gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW);
gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW);
gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0, GPIOD_IN);
if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw) || IS_ERR(gpiod_irq)) {
if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw)) {
nfc_err(&client->dev, "No GPIOs\n");
return -EINVAL;
}
client->irq = gpiod_to_irq(gpiod_irq);
if (client->irq < 0) {
nfc_err(&client->dev, "No IRQ\n");
return -EINVAL;
}
phy->gpio_en = desc_to_gpio(gpiod_en);
phy->gpio_fw = desc_to_gpio(gpiod_fw);
phy->gpio_irq = desc_to_gpio(gpiod_irq);
return 0;
}
......@@ -374,7 +347,6 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
} else if (pdata) {
phy->gpio_en = pdata->gpio_en;
phy->gpio_fw = pdata->gpio_fw;
client->irq = pdata->irq;
} else if (ACPI_HANDLE(&client->dev)) {
r = nxp_nci_i2c_acpi_config(phy);
if (r < 0)
......
......@@ -166,7 +166,6 @@ struct pn544_i2c_phy {
struct nfc_hci_dev *hdev;
unsigned int gpio_en;
unsigned int gpio_irq;
unsigned int gpio_fw;
unsigned int en_polarity;
......@@ -879,9 +878,8 @@ static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client)
{
struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
const struct acpi_device_id *id;
struct gpio_desc *gpiod_en, *gpiod_irq, *gpiod_fw;
struct gpio_desc *gpiod_en, *gpiod_fw;
struct device *dev;
int ret;
if (!client)
return -EINVAL;
......@@ -914,32 +912,9 @@ static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client)
phy->gpio_fw = desc_to_gpio(gpiod_fw);
/* Get IRQ GPIO */
gpiod_irq = devm_gpiod_get_index(dev, PN544_GPIO_NAME_IRQ, 0,
GPIOD_IN);
if (IS_ERR(gpiod_irq)) {
nfc_err(dev, "Unable to get IRQ GPIO\n");
return -ENODEV;
}
phy->gpio_irq = desc_to_gpio(gpiod_irq);
/* Map the pin to an IRQ */
ret = gpiod_to_irq(gpiod_irq);
if (ret < 0) {
nfc_err(dev, "Fail pin IRQ mapping\n");
return ret;
}
nfc_info(dev, "GPIO resource, no:%d irq:%d\n",
desc_to_gpio(gpiod_irq), ret);
client->irq = ret;
return 0;
}
#ifdef CONFIG_OF
static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
{
struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
......@@ -996,15 +971,6 @@ static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
goto err_gpio_fw;
}
/* IRQ */
ret = irq_of_parse_and_map(pp, 0);
if (ret < 0) {
nfc_err(&client->dev,
"Unable to get irq, error: %d\n", ret);
goto err_gpio_fw;
}
client->irq = ret;
return 0;
err_gpio_fw:
......@@ -1015,15 +981,6 @@ static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
return ret;
}
#else
static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
{
return -ENODEV;
}
#endif
static int pn544_hci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -1076,7 +1033,6 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
/* Using ACPI */
} else if (ACPI_HANDLE(&client->dev)) {
r = pn544_hci_i2c_acpi_request_resources(client);
......
......@@ -147,7 +147,7 @@ static struct nci_ops s3fwrn5_nci_ops = {
};
int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload)
const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload)
{
struct s3fwrn5_info *info;
int ret;
......
......@@ -125,7 +125,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
return 0;
}
static struct s3fwrn5_phy_ops i2c_phy_ops = {
static const struct s3fwrn5_phy_ops i2c_phy_ops = {
.set_wake = s3fwrn5_i2c_set_wake,
.set_mode = s3fwrn5_i2c_set_mode,
.get_mode = s3fwrn5_i2c_get_mode,
......
......@@ -44,7 +44,7 @@ struct s3fwrn5_info {
void *phy_id;
struct device *pdev;
struct s3fwrn5_phy_ops *phy_ops;
const struct s3fwrn5_phy_ops *phy_ops;
unsigned int max_payload;
struct s3fwrn5_fw_info fw_info;
......@@ -90,7 +90,7 @@ static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
}
int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload);
const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload);
void s3fwrn5_remove(struct nci_dev *ndev);
int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
......
config NFC_ST_NCI
tristate "STMicroelectronics ST NCI NFC driver"
depends on NFC_NCI
default n
tristate
---help---
STMicroelectronics NFC NCI chips core driver. It implements the chipset
NCI logic and hooks into the NFC kernel APIs. Physical layers will
register against it.
To compile this driver as a module, choose m here. The module will
be called st-nci.
Say N if unsure.
config NFC_ST_NCI_I2C
tristate "NFC ST NCI i2c support"
depends on NFC_ST_NCI && I2C
tristate "STMicroelectronics ST NCI NFC driver (I2C)"
depends on NFC_NCI && I2C
select NFC_ST_NCI
---help---
This module adds support for an I2C interface to the
STMicroelectronics NFC NCI chips familly.
......@@ -23,8 +18,9 @@ config NFC_ST_NCI_I2C
Say N if unsure.
config NFC_ST_NCI_SPI
tristate "NFC ST NCI spi support"
depends on NFC_ST_NCI && SPI
tristate "STMicroelectronics ST NCI NFC driver (SPI)"
depends on NFC_NCI && SPI
select NFC_ST_NCI
---help---
This module adds support for an SPI interface to the
STMicroelectronics NFC NCI chips familly.
......
......@@ -20,8 +20,10 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
......@@ -40,11 +42,7 @@
#define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c"
static struct i2c_device_id st_nci_i2c_id_table[] = {
{ST_NCI_DRIVER_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table);
#define ST_NCI_GPIO_NAME_RESET "clf_reset"
struct st_nci_i2c_phy {
struct i2c_client *i2c_dev;
......@@ -210,7 +208,43 @@ static struct nfc_phy_ops i2c_phy_ops = {
.disable = st_nci_i2c_disable,
};
#ifdef CONFIG_OF
static int st_nci_i2c_acpi_request_resources(struct i2c_client *client)
{
struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
const struct acpi_device_id *id;
struct gpio_desc *gpiod_reset;
struct device *dev;
if (!client)
return -EINVAL;
dev = &client->dev;
/* Match the struct device against a given list of ACPI IDs */
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return -ENODEV;
/* Get RESET GPIO from ACPI */
gpiod_reset = devm_gpiod_get_index(dev, ST_NCI_GPIO_NAME_RESET, 1,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod_reset)) {
nfc_err(dev, "Unable to get RESET GPIO\n");
return -ENODEV;
}
phy->gpio_reset = desc_to_gpio(gpiod_reset);
phy->irq_polarity = irq_get_trigger_type(client->irq);
phy->se_status.is_ese_present =
device_property_present(dev, "ese-present");
phy->se_status.is_uicc_present =
device_property_present(dev, "uicc-present");
return 0;
}
static int st_nci_i2c_of_request_resources(struct i2c_client *client)
{
struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
......@@ -232,7 +266,7 @@ static int st_nci_i2c_of_request_resources(struct i2c_client *client)
/* GPIO request and configuration */
r = devm_gpio_request_one(&client->dev, gpio,
GPIOF_OUT_INIT_HIGH, "clf_reset");
GPIOF_OUT_INIT_HIGH, ST_NCI_GPIO_NAME_RESET);
if (r) {
nfc_err(&client->dev, "Failed to request reset pin\n");
return r;
......@@ -248,12 +282,6 @@ static int st_nci_i2c_of_request_resources(struct i2c_client *client)
return 0;
}
#else
static int st_nci_i2c_of_request_resources(struct i2c_client *client)
{
return -ENODEV;
}
#endif
static int st_nci_i2c_request_resources(struct i2c_client *client)
{
......@@ -272,7 +300,8 @@ static int st_nci_i2c_request_resources(struct i2c_client *client)
phy->irq_polarity = pdata->irq_polarity;
r = devm_gpio_request_one(&client->dev,
phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset");
phy->gpio_reset, GPIOF_OUT_INIT_HIGH,
ST_NCI_GPIO_NAME_RESET);
if (r) {
pr_err("%s : reset gpio_request failed\n", __FILE__);
return r;
......@@ -322,6 +351,12 @@ static int st_nci_i2c_probe(struct i2c_client *client,
"Cannot get platform resources\n");
return r;
}
} else if (ACPI_HANDLE(&client->dev)) {
r = st_nci_i2c_acpi_request_resources(client);
if (r) {
nfc_err(&client->dev, "Cannot get ACPI data\n");
return r;
}
} else {
nfc_err(&client->dev,
"st_nci platform resources not available\n");
......@@ -358,7 +393,19 @@ static int st_nci_i2c_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_OF
static struct i2c_device_id st_nci_i2c_id_table[] = {
{ST_NCI_DRIVER_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table);
static const struct acpi_device_id st_nci_i2c_acpi_match[] = {
{"SMO2101"},
{"SMO2102"},
{}
};
MODULE_DEVICE_TABLE(acpi, st_nci_i2c_acpi_match);
static const struct of_device_id of_st_nci_i2c_match[] = {
{ .compatible = "st,st21nfcb-i2c", },
{ .compatible = "st,st21nfcb_i2c", },
......@@ -366,19 +413,18 @@ static const struct of_device_id of_st_nci_i2c_match[] = {
{}
};
MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match);
#endif
static struct i2c_driver st_nci_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = ST_NCI_I2C_DRIVER_NAME,
.of_match_table = of_match_ptr(of_st_nci_i2c_match),
.acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match),
},
.probe = st_nci_i2c_probe,
.id_table = st_nci_i2c_id_table,
.remove = st_nci_i2c_remove,
};
module_i2c_driver(st_nci_i2c_driver);
MODULE_LICENSE("GPL");
......
......@@ -20,7 +20,6 @@
#include <net/nfc/nci_core.h>
#include "st-nci.h"
#include "ndlc.h"
#define NDLC_TIMER_T1 100
#define NDLC_TIMER_T1_WAIT 400
......
......@@ -331,7 +331,7 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
switch (event) {
case ST_NCI_EVT_CONNECTIVITY:
r = nfc_se_connectivity(ndev->nfc_dev, host);
break;
case ST_NCI_EVT_TRANSACTION:
/* According to specification etsi 102 622
......@@ -392,7 +392,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
}
EXPORT_SYMBOL_GPL(st_nci_hci_event_received);
void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
struct sk_buff *skb)
{
......
......@@ -20,8 +20,10 @@
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
......@@ -41,11 +43,7 @@
#define ST_NCI_SPI_DRIVER_NAME "st_nci_spi"
static struct spi_device_id st_nci_spi_id_table[] = {
{ST_NCI_SPI_DRIVER_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
#define ST_NCI_GPIO_NAME_RESET "clf_reset"
struct st_nci_spi_phy {
struct spi_device *spi_dev;
......@@ -225,7 +223,43 @@ static struct nfc_phy_ops spi_phy_ops = {
.disable = st_nci_spi_disable,
};
#ifdef CONFIG_OF
static int st_nci_spi_acpi_request_resources(struct spi_device *spi_dev)
{
struct st_nci_spi_phy *phy = spi_get_drvdata(spi_dev);
const struct acpi_device_id *id;
struct gpio_desc *gpiod_reset;
struct device *dev;
if (!spi_dev)
return -EINVAL;
dev = &spi_dev->dev;
/* Match the struct device against a given list of ACPI IDs */
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return -ENODEV;
/* Get RESET GPIO from ACPI */
gpiod_reset = devm_gpiod_get_index(dev, ST_NCI_GPIO_NAME_RESET, 1,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod_reset)) {
nfc_err(dev, "Unable to get RESET GPIO\n");
return -ENODEV;
}
phy->gpio_reset = desc_to_gpio(gpiod_reset);
phy->irq_polarity = irq_get_trigger_type(spi_dev->irq);
phy->se_status.is_ese_present =
device_property_present(dev, "ese-present");
phy->se_status.is_uicc_present =
device_property_present(dev, "uicc-present");
return 0;
}
static int st_nci_spi_of_request_resources(struct spi_device *dev)
{
struct st_nci_spi_phy *phy = spi_get_drvdata(dev);
......@@ -247,7 +281,7 @@ static int st_nci_spi_of_request_resources(struct spi_device *dev)
/* GPIO request and configuration */
r = devm_gpio_request_one(&dev->dev, gpio,
GPIOF_OUT_INIT_HIGH, "clf_reset");
GPIOF_OUT_INIT_HIGH, ST_NCI_GPIO_NAME_RESET);
if (r) {
nfc_err(&dev->dev, "Failed to request reset pin\n");
return r;
......@@ -263,12 +297,6 @@ static int st_nci_spi_of_request_resources(struct spi_device *dev)
return 0;
}
#else
static int st_nci_spi_of_request_resources(struct spi_device *dev)
{
return -ENODEV;
}
#endif
static int st_nci_spi_request_resources(struct spi_device *dev)
{
......@@ -287,7 +315,8 @@ static int st_nci_spi_request_resources(struct spi_device *dev)
phy->irq_polarity = pdata->irq_polarity;
r = devm_gpio_request_one(&dev->dev,
phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset");
phy->gpio_reset, GPIOF_OUT_INIT_HIGH,
ST_NCI_GPIO_NAME_RESET);
if (r) {
pr_err("%s : reset gpio_request failed\n", __FILE__);
return r;
......@@ -338,6 +367,12 @@ static int st_nci_spi_probe(struct spi_device *dev)
"Cannot get platform resources\n");
return r;
}
} else if (ACPI_HANDLE(&dev->dev)) {
r = st_nci_spi_acpi_request_resources(dev);
if (r) {
nfc_err(&dev->dev, "Cannot get ACPI data\n");
return r;
}
} else {
nfc_err(&dev->dev,
"st_nci platform resources not available\n");
......@@ -374,24 +409,34 @@ static int st_nci_spi_remove(struct spi_device *dev)
return 0;
}
#ifdef CONFIG_OF
static struct spi_device_id st_nci_spi_id_table[] = {
{ST_NCI_SPI_DRIVER_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
static const struct acpi_device_id st_nci_spi_acpi_match[] = {
{"SMO2101", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, st_nci_spi_acpi_match);
static const struct of_device_id of_st_nci_spi_match[] = {
{ .compatible = "st,st21nfcb-spi", },
{}
};
MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
#endif
static struct spi_driver st_nci_spi_driver = {
.driver = {
.name = ST_NCI_SPI_DRIVER_NAME,
.of_match_table = of_match_ptr(of_st_nci_spi_match),
.acpi_match_table = ACPI_PTR(st_nci_spi_acpi_match),
},
.probe = st_nci_spi_probe,
.id_table = st_nci_spi_id_table,
.remove = st_nci_spi_remove,
};
module_spi_driver(st_nci_spi_driver);
MODULE_LICENSE("GPL");
......
config NFC_ST21NFCA
tristate "STMicroelectronics ST21NFCA NFC driver"
depends on NFC_HCI
tristate
select CRC_CCITT
default n
---help---
STMicroelectronics ST21NFCA core driver. It implements the chipset
HCI logic and hooks into the NFC kernel APIs. Physical layers will
register against it.
To compile this driver as a module, choose m here. The module will
be called st21nfca.
Say N if unsure.
config NFC_ST21NFCA_I2C
tristate "NFC ST21NFCA i2c support"
depends on NFC_ST21NFCA && I2C && NFC_SHDLC
tristate "STMicroelectronics ST21NFCA NFC driver (I2C)"
depends on NFC_HCI && I2C && NFC_SHDLC
select NFC_ST21NFCA
---help---
This module adds support for the STMicroelectronics st21nfca i2c interface.
Select this if your platform is using the i2c bus.
......
......@@ -21,8 +21,10 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
......@@ -60,12 +62,7 @@
#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"
static struct i2c_device_id st21nfca_hci_i2c_id_table[] = {
{ST21NFCA_HCI_DRIVER_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table);
#define ST21NFCA_GPIO_NAME_EN "clf_enable"
struct st21nfca_i2c_phy {
struct i2c_client *i2c_dev;
......@@ -167,7 +164,6 @@ static void st21nfca_hci_i2c_disable(void *phy_id)
{
struct st21nfca_i2c_phy *phy = phy_id;
pr_info("\n");
gpio_set_value(phy->gpio_ena, 0);
phy->powered = 0;
......@@ -210,7 +206,6 @@ static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb)
I2C_DUMP_SKB("st21nfca_hci_i2c_write", skb);
if (phy->hard_fault != 0)
return phy->hard_fault;
......@@ -509,7 +504,41 @@ static struct nfc_phy_ops i2c_phy_ops = {
.disable = st21nfca_hci_i2c_disable,
};
#ifdef CONFIG_OF
static int st21nfca_hci_i2c_acpi_request_resources(struct i2c_client *client)
{
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
const struct acpi_device_id *id;
struct gpio_desc *gpiod_ena;
struct device *dev;
if (!client)
return -EINVAL;
dev = &client->dev;
/* Match the struct device against a given list of ACPI IDs */
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return -ENODEV;
/* Get EN GPIO from ACPI */
gpiod_ena = devm_gpiod_get_index(dev, ST21NFCA_GPIO_NAME_EN, 1,
GPIOD_OUT_LOW);
if (!IS_ERR(gpiod_ena))
phy->gpio_ena = desc_to_gpio(gpiod_ena);
phy->gpio_ena = desc_to_gpio(gpiod_ena);
phy->irq_polarity = irq_get_trigger_type(client->irq);
phy->se_status.is_ese_present =
device_property_present(dev, "ese-present");
phy->se_status.is_uicc_present =
device_property_present(dev, "uicc-present");
return 0;
}
static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
{
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
......@@ -530,7 +559,7 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
/* GPIO request and configuration */
r = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH,
"clf_enable");
ST21NFCA_GPIO_NAME_EN);
if (r) {
nfc_err(&client->dev, "Failed to request enable pin\n");
return r;
......@@ -547,12 +576,6 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
return 0;
}
#else
static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
{
return -ENODEV;
}
#endif
static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
{
......@@ -572,7 +595,8 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
if (phy->gpio_ena > 0) {
r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
GPIOF_OUT_INIT_HIGH, "clf_enable");
GPIOF_OUT_INIT_HIGH,
ST21NFCA_GPIO_NAME_EN);
if (r) {
pr_err("%s : ena gpio_request failed\n", __FILE__);
return r;
......@@ -628,6 +652,12 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
nfc_err(&client->dev, "Cannot get platform resources\n");
return r;
}
} else if (ACPI_HANDLE(&client->dev)) {
r = st21nfca_hci_i2c_acpi_request_resources(client);
if (r) {
nfc_err(&client->dev, "Cannot get ACPI data\n");
return r;
}
} else {
nfc_err(&client->dev, "st21nfca platform resources not available\n");
return -ENODEV;
......@@ -670,26 +700,36 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client)
return 0;
}
#ifdef CONFIG_OF
static struct i2c_device_id st21nfca_hci_i2c_id_table[] = {
{ST21NFCA_HCI_DRIVER_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table);
static const struct acpi_device_id st21nfca_hci_i2c_acpi_match[] = {
{"SMO2100", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, st21nfca_hci_i2c_acpi_match);
static const struct of_device_id of_st21nfca_i2c_match[] = {
{ .compatible = "st,st21nfca-i2c", },
{ .compatible = "st,st21nfca_i2c", },
{}
};
MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
#endif
static struct i2c_driver st21nfca_hci_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = ST21NFCA_HCI_I2C_DRIVER_NAME,
.of_match_table = of_match_ptr(of_st21nfca_i2c_match),
.acpi_match_table = ACPI_PTR(st21nfca_hci_i2c_acpi_match),
},
.probe = st21nfca_hci_i2c_probe,
.id_table = st21nfca_hci_i2c_id_table,
.remove = st21nfca_hci_i2c_remove,
};
module_i2c_driver(st21nfca_hci_i2c_driver);
MODULE_LICENSE("GPL");
......
......@@ -312,6 +312,7 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
switch (event) {
case ST21NFCA_EVT_CONNECTIVITY:
r = nfc_se_connectivity(hdev->ndev, host);
break;
case ST21NFCA_EVT_TRANSACTION:
/*
......
config NFC_ST95HF
tristate "ST95HF NFC Transceiver driver"
depends on SPI && NFC_DIGITAL
help
This enables the ST NFC driver for ST95HF NFC transceiver.
This makes use of SPI framework to communicate with transceiver
and registered with NFC digital core to support Linux NFC framework.
Say Y here to compile support for ST NFC transceiver ST95HF
linux driver into the kernel or say M to compile it as module.
#
# Makefile for STMicroelectronics NFC transceiver ST95HF
#
obj-$(CONFIG_NFC_ST95HF) += st95hf.o
st95hf-objs := spi.o core.o
/*
* --------------------------------------------------------------------
* Driver for ST NFC Transceiver ST95HF
* --------------------------------------------------------------------
* Copyright (C) 2015 STMicroelectronics Pvt. Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/nfc.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/wait.h>
#include <net/nfc/digital.h>
#include <net/nfc/nfc.h>
#include "spi.h"
/* supported protocols */
#define ST95HF_SUPPORTED_PROT (NFC_PROTO_ISO14443_MASK | \
NFC_PROTO_ISO14443_B_MASK | \
NFC_PROTO_ISO15693_MASK)
/* driver capabilities */
#define ST95HF_CAPABILITIES NFC_DIGITAL_DRV_CAPS_IN_CRC
/* Command Send Interface */
/* ST95HF_COMMAND_SEND CMD Ids */
#define ECHO_CMD 0x55
#define WRITE_REGISTER_CMD 0x9
#define PROTOCOL_SELECT_CMD 0x2
#define SEND_RECEIVE_CMD 0x4
/* Select protocol codes */
#define ISO15693_PROTOCOL_CODE 0x1
#define ISO14443A_PROTOCOL_CODE 0x2
#define ISO14443B_PROTOCOL_CODE 0x3
/*
* head room len is 3
* 1 byte for control byte
* 1 byte for cmd
* 1 byte for size
*/
#define ST95HF_HEADROOM_LEN 3
/*
* tailroom is 1 for ISO14443A
* and 0 for ISO14443B/ISO15693,
* hence the max value 1 should be
* taken.
*/
#define ST95HF_TAILROOM_LEN 1
/* Command Response interface */
#define MAX_RESPONSE_BUFFER_SIZE 280
#define ECHORESPONSE 0x55
#define ST95HF_ERR_MASK 0xF
#define ST95HF_TIMEOUT_ERROR 0x87
#define ST95HF_NFCA_CRC_ERR_MASK 0x20
#define ST95HF_NFCB_CRC_ERR_MASK 0x01
/* ST95HF transmission flag values */
#define TRFLAG_NFCA_SHORT_FRAME 0x07
#define TRFLAG_NFCA_STD_FRAME 0x08
#define TRFLAG_NFCA_STD_FRAME_CRC 0x28
/* Misc defs */
#define HIGH 1
#define LOW 0
#define ISO14443A_RATS_REQ 0xE0
#define RATS_TB1_PRESENT_MASK 0x20
#define RATS_TA1_PRESENT_MASK 0x10
#define TB1_FWI_MASK 0xF0
#define WTX_REQ_FROM_TAG 0xF2
#define MAX_CMD_LEN 0x7
#define MAX_CMD_PARAMS 4
struct cmd {
int cmd_len;
unsigned char cmd_id;
unsigned char no_cmd_params;
unsigned char cmd_params[MAX_CMD_PARAMS];
enum req_type req;
};
struct param_list {
int param_offset;
int new_param_val;
};
/*
* List of top-level cmds to be used internally by the driver.
* All these commands are build on top of ST95HF basic commands
* such as SEND_RECEIVE_CMD, PROTOCOL_SELECT_CMD, etc.
* These top level cmds are used internally while implementing various ops of
* digital layer/driver probe or extending the digital framework layer for
* features that are not yet implemented there, for example, WTX cmd handling.
*/
enum st95hf_cmd_list {
CMD_ECHO,
CMD_ISO14443A_CONFIG,
CMD_ISO14443A_DEMOGAIN,
CMD_ISO14443B_DEMOGAIN,
CMD_ISO14443A_PROTOCOL_SELECT,
CMD_ISO14443B_PROTOCOL_SELECT,
CMD_WTX_RESPONSE,
CMD_FIELD_OFF,
CMD_ISO15693_PROTOCOL_SELECT,
};
static const struct cmd cmd_array[] = {
[CMD_ECHO] = {
.cmd_len = 0x2,
.cmd_id = ECHO_CMD,
.no_cmd_params = 0,
.req = SYNC,
},
[CMD_ISO14443A_CONFIG] = {
.cmd_len = 0x7,
.cmd_id = WRITE_REGISTER_CMD,
.no_cmd_params = 0x4,
.cmd_params = {0x3A, 0x00, 0x5A, 0x04},
.req = SYNC,
},
[CMD_ISO14443A_DEMOGAIN] = {
.cmd_len = 0x7,
.cmd_id = WRITE_REGISTER_CMD,
.no_cmd_params = 0x4,
.cmd_params = {0x68, 0x01, 0x01, 0xDF},
.req = SYNC,
},
[CMD_ISO14443B_DEMOGAIN] = {
.cmd_len = 0x7,
.cmd_id = WRITE_REGISTER_CMD,
.no_cmd_params = 0x4,
.cmd_params = {0x68, 0x01, 0x01, 0x51},
.req = SYNC,
},
[CMD_ISO14443A_PROTOCOL_SELECT] = {
.cmd_len = 0x7,
.cmd_id = PROTOCOL_SELECT_CMD,
.no_cmd_params = 0x4,
.cmd_params = {ISO14443A_PROTOCOL_CODE, 0x00, 0x01, 0xA0},
.req = SYNC,
},
[CMD_ISO14443B_PROTOCOL_SELECT] = {
.cmd_len = 0x7,
.cmd_id = PROTOCOL_SELECT_CMD,
.no_cmd_params = 0x4,
.cmd_params = {ISO14443B_PROTOCOL_CODE, 0x01, 0x03, 0xFF},
.req = SYNC,
},
[CMD_WTX_RESPONSE] = {
.cmd_len = 0x6,
.cmd_id = SEND_RECEIVE_CMD,
.no_cmd_params = 0x3,
.cmd_params = {0xF2, 0x00, TRFLAG_NFCA_STD_FRAME_CRC},
.req = ASYNC,
},
[CMD_FIELD_OFF] = {
.cmd_len = 0x5,
.cmd_id = PROTOCOL_SELECT_CMD,
.no_cmd_params = 0x2,
.cmd_params = {0x0, 0x0},
.req = SYNC,
},
[CMD_ISO15693_PROTOCOL_SELECT] = {
.cmd_len = 0x5,
.cmd_id = PROTOCOL_SELECT_CMD,
.no_cmd_params = 0x2,
.cmd_params = {ISO15693_PROTOCOL_CODE, 0x0D},
.req = SYNC,
},
};
/* st95_digital_cmd_complete_arg stores client context */
struct st95_digital_cmd_complete_arg {
struct sk_buff *skb_resp;
nfc_digital_cmd_complete_t complete_cb;
void *cb_usrarg;
bool rats;
};
/*
* structure containing ST95HF driver specific data.
* @spicontext: structure containing information required
* for spi communication between st95hf and host.
* @ddev: nfc digital device object.
* @nfcdev: nfc device object.
* @enable_gpio: gpio used to enable st95hf transceiver.
* @complete_cb_arg: structure to store various context information
* that is passed from nfc requesting thread to the threaded ISR.
* @st95hf_supply: regulator "consumer" for NFC device.
* @sendrcv_trflag: last byte of frame send by sendrecv command
* of st95hf. This byte contains transmission flag info.
* @exchange_lock: semaphore used for signaling the st95hf_remove
* function that the last outstanding async nfc request is finished.
* @rm_lock: mutex for ensuring safe access of nfc digital object
* from threaded ISR. Usage of this mutex avoids any race between
* deletion of the object from st95hf_remove() and its access from
* the threaded ISR.
* @nfcdev_free: flag to have the state of nfc device object.
* [alive | died]
* @current_protocol: current nfc protocol.
* @current_rf_tech: current rf technology.
* @fwi: frame waiting index, received in reply of RATS according to
* digital protocol.
*/
struct st95hf_context {
struct st95hf_spi_context spicontext;
struct nfc_digital_dev *ddev;
struct nfc_dev *nfcdev;
unsigned int enable_gpio;
struct st95_digital_cmd_complete_arg complete_cb_arg;
struct regulator *st95hf_supply;
unsigned char sendrcv_trflag;
struct semaphore exchange_lock;
struct mutex rm_lock;
bool nfcdev_free;
u8 current_protocol;
u8 current_rf_tech;
int fwi;
};
/*
* st95hf_send_recv_cmd() is for sending commands to ST95HF
* that are described in the cmd_array[]. It can optionally
* receive the response if the cmd request is of type
* SYNC. For that to happen caller must pass true to recv_res.
* For ASYNC request, recv_res is ignored and the
* function will never try to receive the response on behalf
* of the caller.
*/
static int st95hf_send_recv_cmd(struct st95hf_context *st95context,
enum st95hf_cmd_list cmd,
int no_modif,
struct param_list *list_array,
bool recv_res)
{
unsigned char spi_cmd_buffer[MAX_CMD_LEN];
int i, ret;
struct device *dev = &st95context->spicontext.spidev->dev;
if (cmd_array[cmd].cmd_len > MAX_CMD_LEN)
return -EINVAL;
if (cmd_array[cmd].no_cmd_params < no_modif)
return -EINVAL;
if (no_modif && !list_array)
return -EINVAL;
spi_cmd_buffer[0] = ST95HF_COMMAND_SEND;
spi_cmd_buffer[1] = cmd_array[cmd].cmd_id;
spi_cmd_buffer[2] = cmd_array[cmd].no_cmd_params;
memcpy(&spi_cmd_buffer[3], cmd_array[cmd].cmd_params,
spi_cmd_buffer[2]);
for (i = 0; i < no_modif; i++) {
if (list_array[i].param_offset >= cmd_array[cmd].no_cmd_params)
return -EINVAL;
spi_cmd_buffer[3 + list_array[i].param_offset] =
list_array[i].new_param_val;
}
ret = st95hf_spi_send(&st95context->spicontext,
spi_cmd_buffer,
cmd_array[cmd].cmd_len,
cmd_array[cmd].req);
if (ret) {
dev_err(dev, "st95hf_spi_send failed with error %d\n", ret);
return ret;
}
if (cmd_array[cmd].req == SYNC && recv_res) {
unsigned char st95hf_response_arr[2];
ret = st95hf_spi_recv_response(&st95context->spicontext,
st95hf_response_arr);
if (ret < 0) {
dev_err(dev, "spi error from st95hf_spi_recv_response(), err = 0x%x\n",
ret);
return ret;
}
if (st95hf_response_arr[0]) {
dev_err(dev, "st95hf error from st95hf_spi_recv_response(), err = 0x%x\n",
st95hf_response_arr[0]);
return -EIO;
}
}
return 0;
}
static int st95hf_echo_command(struct st95hf_context *st95context)
{
int result = 0;
unsigned char echo_response;
result = st95hf_send_recv_cmd(st95context, CMD_ECHO, 0, NULL, false);
if (result)
return result;
/* If control reached here, response can be taken */
result = st95hf_spi_recv_echo_res(&st95context->spicontext,
&echo_response);
if (result) {
dev_err(&st95context->spicontext.spidev->dev,
"err: echo response receieve error = 0x%x\n", result);
return result;
}
if (echo_response == ECHORESPONSE)
return 0;
dev_err(&st95context->spicontext.spidev->dev, "err: echo res is 0x%x\n",
echo_response);
return -EIO;
}
static int secondary_configuration_type4a(struct st95hf_context *stcontext)
{
int result = 0;
struct device *dev = &stcontext->nfcdev->dev;
/* 14443A config setting after select protocol */
result = st95hf_send_recv_cmd(stcontext,
CMD_ISO14443A_CONFIG,
0,
NULL,
true);
if (result) {
dev_err(dev, "type a config cmd, err = 0x%x\n", result);
return result;
}
/* 14443A demo gain setting */
result = st95hf_send_recv_cmd(stcontext,
CMD_ISO14443A_DEMOGAIN,
0,
NULL,
true);
if (result)
dev_err(dev, "type a demogain cmd, err = 0x%x\n", result);
return result;
}
static int secondary_configuration_type4b(struct st95hf_context *stcontext)
{
int result = 0;
struct device *dev = &stcontext->nfcdev->dev;
result = st95hf_send_recv_cmd(stcontext,
CMD_ISO14443B_DEMOGAIN,
0,
NULL,
true);
if (result)
dev_err(dev, "type b demogain cmd, err = 0x%x\n", result);
return result;
}
static int st95hf_select_protocol(struct st95hf_context *stcontext, int type)
{
int result = 0;
struct device *dev;
dev = &stcontext->nfcdev->dev;
switch (type) {
case NFC_DIGITAL_RF_TECH_106A:
stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_106A;
result = st95hf_send_recv_cmd(stcontext,
CMD_ISO14443A_PROTOCOL_SELECT,
0,
NULL,
true);
if (result) {
dev_err(dev, "protocol sel, err = 0x%x\n",
result);
return result;
}
/* secondary config. for 14443Type 4A after protocol select */
result = secondary_configuration_type4a(stcontext);
if (result) {
dev_err(dev, "type a secondary config, err = 0x%x\n",
result);
return result;
}
break;
case NFC_DIGITAL_RF_TECH_106B:
stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_106B;
result = st95hf_send_recv_cmd(stcontext,
CMD_ISO14443B_PROTOCOL_SELECT,
0,
NULL,
true);
if (result) {
dev_err(dev, "protocol sel send, err = 0x%x\n",
result);
return result;
}
/*
* delay of 5-6 ms is required after select protocol
* command in case of ISO14443 Type B
*/
usleep_range(50000, 60000);
/* secondary config. for 14443Type 4B after protocol select */
result = secondary_configuration_type4b(stcontext);
if (result) {
dev_err(dev, "type b secondary config, err = 0x%x\n",
result);
return result;
}
break;
case NFC_DIGITAL_RF_TECH_ISO15693:
stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_ISO15693;
result = st95hf_send_recv_cmd(stcontext,
CMD_ISO15693_PROTOCOL_SELECT,
0,
NULL,
true);
if (result) {
dev_err(dev, "protocol sel send, err = 0x%x\n",
result);
return result;
}
break;
default:
return -EINVAL;
}
return 0;
}
static void st95hf_send_st95enable_negativepulse(struct st95hf_context *st95con)
{
/* First make irq_in pin high */
gpio_set_value(st95con->enable_gpio, HIGH);
/* wait for 1 milisecond */
usleep_range(1000, 2000);
/* Make irq_in pin low */
gpio_set_value(st95con->enable_gpio, LOW);
/* wait for minimum interrupt pulse to make st95 active */
usleep_range(1000, 2000);
/* At end make it high */
gpio_set_value(st95con->enable_gpio, HIGH);
}
/*
* Send a reset sequence over SPI bus (Reset command + wait 3ms +
* negative pulse on st95hf enable gpio
*/
static int st95hf_send_spi_reset_sequence(struct st95hf_context *st95context)
{
int result = 0;
unsigned char reset_cmd = ST95HF_COMMAND_RESET;
result = st95hf_spi_send(&st95context->spicontext,
&reset_cmd,
ST95HF_RESET_CMD_LEN,
ASYNC);
if (result) {
dev_err(&st95context->spicontext.spidev->dev,
"spi reset sequence cmd error = %d", result);
return result;
}
/* wait for 3 milisecond to complete the controller reset process */
usleep_range(3000, 4000);
/* send negative pulse to make st95hf active */
st95hf_send_st95enable_negativepulse(st95context);
/* wait for 10 milisecond : HFO setup time */
usleep_range(10000, 20000);
return result;
}
static int st95hf_por_sequence(struct st95hf_context *st95context)
{
int nth_attempt = 1;
int result;
st95hf_send_st95enable_negativepulse(st95context);
usleep_range(5000, 6000);
do {
/* send an ECHO command and checks ST95HF response */
result = st95hf_echo_command(st95context);
dev_dbg(&st95context->spicontext.spidev->dev,
"response from echo function = 0x%x, attempt = %d\n",
result, nth_attempt);
if (!result)
return 0;
/* send an pulse on IRQ in case of the chip is on sleep state */
if (nth_attempt == 2)
st95hf_send_st95enable_negativepulse(st95context);
else
st95hf_send_spi_reset_sequence(st95context);
/* delay of 50 milisecond */
usleep_range(50000, 51000);
} while (nth_attempt++ < 3);
return -ETIMEDOUT;
}
static int iso14443_config_fdt(struct st95hf_context *st95context, int wtxm)
{
int result = 0;
struct device *dev = &st95context->spicontext.spidev->dev;
struct nfc_digital_dev *nfcddev = st95context->ddev;
unsigned char pp_typeb;
struct param_list new_params[2];
pp_typeb = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[2];
if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 &&
st95context->fwi < 4)
st95context->fwi = 4;
new_params[0].param_offset = 2;
if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
new_params[0].new_param_val = st95context->fwi;
else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
new_params[0].new_param_val = pp_typeb;
new_params[1].param_offset = 3;
new_params[1].new_param_val = wtxm;
switch (nfcddev->curr_protocol) {
case NFC_PROTO_ISO14443:
result = st95hf_send_recv_cmd(st95context,
CMD_ISO14443A_PROTOCOL_SELECT,
2,
new_params,
true);
if (result) {
dev_err(dev, "WTX type a sel proto, err = 0x%x\n",
result);
return result;
}
/* secondary config. for 14443Type 4A after protocol select */
result = secondary_configuration_type4a(st95context);
if (result) {
dev_err(dev, "WTX type a second. config, err = 0x%x\n",
result);
return result;
}
break;
case NFC_PROTO_ISO14443_B:
result = st95hf_send_recv_cmd(st95context,
CMD_ISO14443B_PROTOCOL_SELECT,
2,
new_params,
true);
if (result) {
dev_err(dev, "WTX type b sel proto, err = 0x%x\n",
result);
return result;
}
/* secondary config. for 14443Type 4B after protocol select */
result = secondary_configuration_type4b(st95context);
if (result) {
dev_err(dev, "WTX type b second. config, err = 0x%x\n",
result);
return result;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int st95hf_handle_wtx(struct st95hf_context *stcontext,
bool new_wtx,
int wtx_val)
{
int result = 0;
unsigned char val_mm = 0;
struct param_list new_params[1];
struct nfc_digital_dev *nfcddev = stcontext->ddev;
struct device *dev = &stcontext->nfcdev->dev;
if (new_wtx) {
result = iso14443_config_fdt(stcontext, wtx_val & 0x3f);
if (result) {
dev_err(dev, "Config. setting error on WTX req, err = 0x%x\n",
result);
return result;
}
/* Send response of wtx with ASYNC as no response expected */
new_params[0].param_offset = 1;
new_params[0].new_param_val = wtx_val;
result = st95hf_send_recv_cmd(stcontext,
CMD_WTX_RESPONSE,
1,
new_params,
false);
if (result)
dev_err(dev, "WTX response send, err = 0x%x\n", result);
return result;
}
/* if no new wtx, cofigure with default values */
if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
val_mm = cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[3];
else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
val_mm = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[3];
result = iso14443_config_fdt(stcontext, val_mm);
if (result)
dev_err(dev, "Default config. setting error after WTX processing, err = 0x%x\n",
result);
return result;
}
static int st95hf_error_handling(struct st95hf_context *stcontext,
struct sk_buff *skb_resp,
int res_len)
{
int result = 0;
unsigned char error_byte;
struct device *dev = &stcontext->nfcdev->dev;
/* First check ST95HF specific error */
if (skb_resp->data[0] & ST95HF_ERR_MASK) {
if (skb_resp->data[0] == ST95HF_TIMEOUT_ERROR)
result = -ETIMEDOUT;
else
result = -EIO;
return result;
}
/* Check for CRC err only if CRC is present in the tag response */
switch (stcontext->current_rf_tech) {
case NFC_DIGITAL_RF_TECH_106A:
if (stcontext->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC) {
error_byte = skb_resp->data[res_len - 3];
if (error_byte & ST95HF_NFCA_CRC_ERR_MASK) {
/* CRC error occurred */
dev_err(dev, "CRC error, byte received = 0x%x\n",
error_byte);
result = -EIO;
}
}
break;
case NFC_DIGITAL_RF_TECH_106B:
case NFC_DIGITAL_RF_TECH_ISO15693:
error_byte = skb_resp->data[res_len - 1];
if (error_byte & ST95HF_NFCB_CRC_ERR_MASK) {
/* CRC error occurred */
dev_err(dev, "CRC error, byte received = 0x%x\n",
error_byte);
result = -EIO;
}
break;
}
return result;
}
static int st95hf_response_handler(struct st95hf_context *stcontext,
struct sk_buff *skb_resp,
int res_len)
{
int result = 0;
int skb_len;
unsigned char val_mm;
struct nfc_digital_dev *nfcddev = stcontext->ddev;
struct device *dev = &stcontext->nfcdev->dev;
struct st95_digital_cmd_complete_arg *cb_arg;
cb_arg = &stcontext->complete_cb_arg;
/* Process the response */
skb_put(skb_resp, res_len);
/* Remove st95 header */
skb_pull(skb_resp, 2);
skb_len = skb_resp->len;
/* check if it is case of RATS request reply & FWI is present */
if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 && cb_arg->rats &&
(skb_resp->data[1] & RATS_TB1_PRESENT_MASK)) {
if (skb_resp->data[1] & RATS_TA1_PRESENT_MASK)
stcontext->fwi =
(skb_resp->data[3] & TB1_FWI_MASK) >> 4;
else
stcontext->fwi =
(skb_resp->data[2] & TB1_FWI_MASK) >> 4;
val_mm = cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[3];
result = iso14443_config_fdt(stcontext, val_mm);
if (result) {
dev_err(dev, "error in config_fdt to handle fwi of ATS, error=%d\n",
result);
return result;
}
}
cb_arg->rats = false;
/* Remove CRC bytes only if received frames data has an eod (CRC) */
switch (stcontext->current_rf_tech) {
case NFC_DIGITAL_RF_TECH_106A:
if (stcontext->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC)
skb_trim(skb_resp, (skb_len - 5));
else
skb_trim(skb_resp, (skb_len - 3));
break;
case NFC_DIGITAL_RF_TECH_106B:
case NFC_DIGITAL_RF_TECH_ISO15693:
skb_trim(skb_resp, (skb_len - 3));
break;
}
return result;
}
static irqreturn_t st95hf_irq_handler(int irq, void *st95hfcontext)
{
struct st95hf_context *stcontext =
(struct st95hf_context *)st95hfcontext;
if (stcontext->spicontext.req_issync) {
complete(&stcontext->spicontext.done);
stcontext->spicontext.req_issync = false;
return IRQ_HANDLED;
}
return IRQ_WAKE_THREAD;
}
static irqreturn_t st95hf_irq_thread_handler(int irq, void *st95hfcontext)
{
int result = 0;
int res_len;
static bool wtx;
struct device *dev;
struct device *spidevice;
struct nfc_digital_dev *nfcddev;
struct sk_buff *skb_resp;
struct st95hf_context *stcontext =
(struct st95hf_context *)st95hfcontext;
struct st95_digital_cmd_complete_arg *cb_arg;
spidevice = &stcontext->spicontext.spidev->dev;
/*
* check semaphore, if not down() already, then we don't
* know in which context the ISR is called and surely it
* will be a bug. Note that down() of the semaphore is done
* in the corresponding st95hf_in_send_cmd() and then
* only this ISR should be called. ISR will up() the
* semaphore before leaving. Hence when the ISR is called
* the correct behaviour is down_trylock() should always
* return 1 (indicating semaphore cant be taken and hence no
* change in semaphore count).
* If not, then we up() the semaphore and crash on
* a BUG() !
*/
if (!down_trylock(&stcontext->exchange_lock)) {
up(&stcontext->exchange_lock);
WARN(1, "unknown context in ST95HF ISR");
return IRQ_NONE;
}
cb_arg = &stcontext->complete_cb_arg;
skb_resp = cb_arg->skb_resp;
mutex_lock(&stcontext->rm_lock);
res_len = st95hf_spi_recv_response(&stcontext->spicontext,
skb_resp->data);
if (res_len < 0) {
dev_err(spidevice, "TISR spi response err = 0x%x\n", res_len);
result = res_len;
goto end;
}
/* if stcontext->nfcdev_free is true, it means remove already ran */
if (stcontext->nfcdev_free) {
result = -ENODEV;
goto end;
}
dev = &stcontext->nfcdev->dev;
nfcddev = stcontext->ddev;
if (skb_resp->data[2] == WTX_REQ_FROM_TAG) {
/* Request for new FWT from tag */
result = st95hf_handle_wtx(stcontext, true, skb_resp->data[3]);
if (result)
goto end;
wtx = true;
mutex_unlock(&stcontext->rm_lock);
return IRQ_HANDLED;
}
result = st95hf_error_handling(stcontext, skb_resp, res_len);
if (result)
goto end;
result = st95hf_response_handler(stcontext, skb_resp, res_len);
if (result)
goto end;
/*
* If select protocol is done on wtx req. do select protocol
* again with default values
*/
if (wtx) {
wtx = false;
result = st95hf_handle_wtx(stcontext, false, 0);
if (result)
goto end;
}
/* call digital layer callback */
cb_arg->complete_cb(stcontext->ddev, cb_arg->cb_usrarg, skb_resp);
/* up the semaphore before returning */
up(&stcontext->exchange_lock);
mutex_unlock(&stcontext->rm_lock);
return IRQ_HANDLED;
end:
kfree_skb(skb_resp);
wtx = false;
cb_arg->rats = false;
skb_resp = ERR_PTR(result);
/* call of callback with error */
cb_arg->complete_cb(stcontext->ddev, cb_arg->cb_usrarg, skb_resp);
/* up the semaphore before returning */
up(&stcontext->exchange_lock);
mutex_unlock(&stcontext->rm_lock);
return IRQ_HANDLED;
}
/* NFC ops functions definition */
static int st95hf_in_configure_hw(struct nfc_digital_dev *ddev,
int type,
int param)
{
struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
if (type == NFC_DIGITAL_CONFIG_RF_TECH)
return st95hf_select_protocol(stcontext, param);
if (type == NFC_DIGITAL_CONFIG_FRAMING) {
switch (param) {
case NFC_DIGITAL_FRAMING_NFCA_SHORT:
stcontext->sendrcv_trflag = TRFLAG_NFCA_SHORT_FRAME;
break;
case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
stcontext->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME;
break;
case NFC_DIGITAL_FRAMING_NFCA_T4T:
case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
stcontext->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME_CRC;
break;
case NFC_DIGITAL_FRAMING_NFCB:
case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
case NFC_DIGITAL_FRAMING_ISO15693_T5T:
break;
}
}
return 0;
}
static int rf_off(struct st95hf_context *stcontext)
{
int rc;
struct device *dev;
dev = &stcontext->nfcdev->dev;
rc = st95hf_send_recv_cmd(stcontext, CMD_FIELD_OFF, 0, NULL, true);
if (rc)
dev_err(dev, "protocol sel send field off, err = 0x%x\n", rc);
return rc;
}
static int st95hf_in_send_cmd(struct nfc_digital_dev *ddev,
struct sk_buff *skb,
u16 timeout,
nfc_digital_cmd_complete_t cb,
void *arg)
{
struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
int rc;
struct sk_buff *skb_resp;
int len_data_to_tag = 0;
skb_resp = nfc_alloc_recv_skb(MAX_RESPONSE_BUFFER_SIZE, GFP_KERNEL);
if (!skb_resp) {
rc = -ENOMEM;
goto error;
}
switch (stcontext->current_rf_tech) {
case NFC_DIGITAL_RF_TECH_106A:
len_data_to_tag = skb->len + 1;
*skb_put(skb, 1) = stcontext->sendrcv_trflag;
break;
case NFC_DIGITAL_RF_TECH_106B:
case NFC_DIGITAL_RF_TECH_ISO15693:
len_data_to_tag = skb->len;
break;
default:
rc = -EINVAL;
goto free_skb_resp;
}
skb_push(skb, 3);
skb->data[0] = ST95HF_COMMAND_SEND;
skb->data[1] = SEND_RECEIVE_CMD;
skb->data[2] = len_data_to_tag;
stcontext->complete_cb_arg.skb_resp = skb_resp;
stcontext->complete_cb_arg.cb_usrarg = arg;
stcontext->complete_cb_arg.complete_cb = cb;
if ((skb->data[3] == ISO14443A_RATS_REQ) &&
ddev->curr_protocol == NFC_PROTO_ISO14443)
stcontext->complete_cb_arg.rats = true;
/*
* down the semaphore to indicate to remove func that an
* ISR is pending, note that it will not block here in any case.
* If found blocked, it is a BUG!
*/
rc = down_killable(&stcontext->exchange_lock);
if (rc) {
WARN(1, "Semaphore is not found up in st95hf_in_send_cmd\n");
return rc;
}
rc = st95hf_spi_send(&stcontext->spicontext, skb->data,
skb->len,
ASYNC);
if (rc) {
dev_err(&stcontext->nfcdev->dev,
"Error %d trying to perform data_exchange", rc);
/* up the semaphore since ISR will never come in this case */
up(&stcontext->exchange_lock);
goto free_skb_resp;
}
kfree_skb(skb);
return rc;
free_skb_resp:
kfree_skb(skb_resp);
error:
return rc;
}
/* p2p will be supported in a later release ! */
static int st95hf_tg_configure_hw(struct nfc_digital_dev *ddev,
int type,
int param)
{
return 0;
}
static int st95hf_tg_send_cmd(struct nfc_digital_dev *ddev,
struct sk_buff *skb,
u16 timeout,
nfc_digital_cmd_complete_t cb,
void *arg)
{
return 0;
}
static int st95hf_tg_listen(struct nfc_digital_dev *ddev,
u16 timeout,
nfc_digital_cmd_complete_t cb,
void *arg)
{
return 0;
}
static int st95hf_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech)
{
return 0;
}
static int st95hf_switch_rf(struct nfc_digital_dev *ddev, bool on)
{
u8 rf_tech;
struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
rf_tech = ddev->curr_rf_tech;
if (on)
/* switch on RF field */
return st95hf_select_protocol(stcontext, rf_tech);
/* switch OFF RF field */
return rf_off(stcontext);
}
/* TODO st95hf_abort_cmd */
static void st95hf_abort_cmd(struct nfc_digital_dev *ddev)
{
}
static struct nfc_digital_ops st95hf_nfc_digital_ops = {
.in_configure_hw = st95hf_in_configure_hw,
.in_send_cmd = st95hf_in_send_cmd,
.tg_listen = st95hf_tg_listen,
.tg_configure_hw = st95hf_tg_configure_hw,
.tg_send_cmd = st95hf_tg_send_cmd,
.tg_get_rf_tech = st95hf_tg_get_rf_tech,
.switch_rf = st95hf_switch_rf,
.abort_cmd = st95hf_abort_cmd,
};
static const struct spi_device_id st95hf_id[] = {
{ "st95hf", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, st95hf_id);
static int st95hf_probe(struct spi_device *nfc_spi_dev)
{
int ret;
struct st95hf_context *st95context;
struct st95hf_spi_context *spicontext;
nfc_info(&nfc_spi_dev->dev, "ST95HF driver probe called.\n");
st95context = devm_kzalloc(&nfc_spi_dev->dev,
sizeof(struct st95hf_context),
GFP_KERNEL);
if (!st95context)
return -ENOMEM;
spicontext = &st95context->spicontext;
spicontext->spidev = nfc_spi_dev;
st95context->fwi =
cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[2];
if (device_property_present(&nfc_spi_dev->dev, "st95hfvin")) {
st95context->st95hf_supply =
devm_regulator_get(&nfc_spi_dev->dev,
"st95hfvin");
if (IS_ERR(st95context->st95hf_supply)) {
dev_err(&nfc_spi_dev->dev, "failed to acquire regulator\n");
return PTR_ERR(st95context->st95hf_supply);
}
ret = regulator_enable(st95context->st95hf_supply);
if (ret) {
dev_err(&nfc_spi_dev->dev, "failed to enable regulator\n");
return ret;
}
}
init_completion(&spicontext->done);
mutex_init(&spicontext->spi_lock);
/*
* Store spicontext in spi device object for using it in
* remove function
*/
dev_set_drvdata(&nfc_spi_dev->dev, spicontext);
st95context->enable_gpio =
of_get_named_gpio(nfc_spi_dev->dev.of_node,
"enable-gpio",
0);
if (!gpio_is_valid(st95context->enable_gpio)) {
dev_err(&nfc_spi_dev->dev, "No valid enable gpio\n");
ret = st95context->enable_gpio;
goto err_disable_regulator;
}
ret = devm_gpio_request_one(&nfc_spi_dev->dev, st95context->enable_gpio,
GPIOF_DIR_OUT | GPIOF_INIT_HIGH,
"enable_gpio");
if (ret)
goto err_disable_regulator;
if (nfc_spi_dev->irq > 0) {
if (devm_request_threaded_irq(&nfc_spi_dev->dev,
nfc_spi_dev->irq,
st95hf_irq_handler,
st95hf_irq_thread_handler,
IRQF_TRIGGER_FALLING,
"st95hf",
(void *)st95context) < 0) {
dev_err(&nfc_spi_dev->dev, "err: irq request for st95hf is failed\n");
ret = -EINVAL;
goto err_disable_regulator;
}
} else {
dev_err(&nfc_spi_dev->dev, "not a valid IRQ associated with ST95HF\n");
ret = -EINVAL;
goto err_disable_regulator;
}
/*
* First reset SPI to handle warm reset of the system.
* It will put the ST95HF device in Power ON state
* which make the state of device identical to state
* at the time of cold reset of the system.
*/
ret = st95hf_send_spi_reset_sequence(st95context);
if (ret) {
dev_err(&nfc_spi_dev->dev, "err: spi_reset_sequence failed\n");
goto err_disable_regulator;
}
/* call PowerOnReset sequence of ST95hf to activate it */
ret = st95hf_por_sequence(st95context);
if (ret) {
dev_err(&nfc_spi_dev->dev, "err: por seq failed for st95hf\n");
goto err_disable_regulator;
}
/* create NFC dev object and register with NFC Subsystem */
st95context->ddev = nfc_digital_allocate_device(&st95hf_nfc_digital_ops,
ST95HF_SUPPORTED_PROT,
ST95HF_CAPABILITIES,
ST95HF_HEADROOM_LEN,
ST95HF_TAILROOM_LEN);
if (!st95context->ddev) {
ret = -ENOMEM;
goto err_disable_regulator;
}
st95context->nfcdev = st95context->ddev->nfc_dev;
nfc_digital_set_parent_dev(st95context->ddev, &nfc_spi_dev->dev);
ret = nfc_digital_register_device(st95context->ddev);
if (ret) {
dev_err(&st95context->nfcdev->dev, "st95hf registration failed\n");
goto err_free_digital_device;
}
/* store st95context in nfc device object */
nfc_digital_set_drvdata(st95context->ddev, st95context);
sema_init(&st95context->exchange_lock, 1);
mutex_init(&st95context->rm_lock);
return ret;
err_free_digital_device:
nfc_digital_free_device(st95context->ddev);
err_disable_regulator:
if (st95context->st95hf_supply)
regulator_disable(st95context->st95hf_supply);
return ret;
}
static int st95hf_remove(struct spi_device *nfc_spi_dev)
{
int result = 0;
unsigned char reset_cmd = ST95HF_COMMAND_RESET;
struct st95hf_spi_context *spictx = dev_get_drvdata(&nfc_spi_dev->dev);
struct st95hf_context *stcontext = container_of(spictx,
struct st95hf_context,
spicontext);
mutex_lock(&stcontext->rm_lock);
nfc_digital_unregister_device(stcontext->ddev);
nfc_digital_free_device(stcontext->ddev);
stcontext->nfcdev_free = true;
mutex_unlock(&stcontext->rm_lock);
/* if last in_send_cmd's ISR is pending, wait for it to finish */
result = down_killable(&stcontext->exchange_lock);
if (result == -EINTR)
dev_err(&spictx->spidev->dev, "sleep for semaphore interrupted by signal\n");
/* next reset the ST95HF controller */
result = st95hf_spi_send(&stcontext->spicontext,
&reset_cmd,
ST95HF_RESET_CMD_LEN,
ASYNC);
if (result) {
dev_err(&spictx->spidev->dev,
"ST95HF reset failed in remove() err = %d\n", result);
return result;
}
/* wait for 3 ms to complete the controller reset process */
usleep_range(3000, 4000);
/* disable regulator */
if (stcontext->st95hf_supply)
regulator_disable(stcontext->st95hf_supply);
return result;
}
/* Register as SPI protocol driver */
static struct spi_driver st95hf_driver = {
.driver = {
.name = "st95hf",
.owner = THIS_MODULE,
},
.id_table = st95hf_id,
.probe = st95hf_probe,
.remove = st95hf_remove,
};
module_spi_driver(st95hf_driver);
MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
MODULE_DESCRIPTION("ST NFC Transceiver ST95HF driver");
MODULE_LICENSE("GPL v2");
/*
* ----------------------------------------------------------------------------
* drivers/nfc/st95hf/spi.c function definitions for SPI communication
* ----------------------------------------------------------------------------
* Copyright (C) 2015 STMicroelectronics Pvt. Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "spi.h"
/* Function to send user provided buffer to ST95HF through SPI */
int st95hf_spi_send(struct st95hf_spi_context *spicontext,
unsigned char *buffertx,
int datalen,
enum req_type reqtype)
{
struct spi_message m;
int result = 0;
struct spi_device *spidev = spicontext->spidev;
struct spi_transfer tx_transfer = {
.tx_buf = buffertx,
.len = datalen,
};
mutex_lock(&spicontext->spi_lock);
if (reqtype == SYNC) {
spicontext->req_issync = true;
reinit_completion(&spicontext->done);
} else {
spicontext->req_issync = false;
}
spi_message_init(&m);
spi_message_add_tail(&tx_transfer, &m);
result = spi_sync(spidev, &m);
if (result) {
dev_err(&spidev->dev, "error: sending cmd to st95hf using SPI = %d\n",
result);
mutex_unlock(&spicontext->spi_lock);
return result;
}
/* return for asynchronous or no-wait case */
if (reqtype == ASYNC) {
mutex_unlock(&spicontext->spi_lock);
return 0;
}
result = wait_for_completion_timeout(&spicontext->done,
msecs_to_jiffies(1000));
/* check for timeout or success */
if (!result) {
dev_err(&spidev->dev, "error: response not ready timeout\n");
result = -ETIMEDOUT;
} else {
result = 0;
}
mutex_unlock(&spicontext->spi_lock);
return result;
}
EXPORT_SYMBOL_GPL(st95hf_spi_send);
/* Function to Receive command Response */
int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
unsigned char *receivebuff)
{
int len = 0;
struct spi_transfer tx_takedata;
struct spi_message m;
struct spi_device *spidev = spicontext->spidev;
unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
struct spi_transfer t[2] = {
{.tx_buf = &readdata_cmd, .len = 1,},
{.rx_buf = receivebuff, .len = 2, .cs_change = 1,},
};
int ret = 0;
memset(&tx_takedata, 0x0, sizeof(struct spi_transfer));
mutex_lock(&spicontext->spi_lock);
/* First spi transfer to know the length of valid data */
spi_message_init(&m);
spi_message_add_tail(&t[0], &m);
spi_message_add_tail(&t[1], &m);
ret = spi_sync(spidev, &m);
if (ret) {
dev_err(&spidev->dev, "spi_recv_resp, data length error = %d\n",
ret);
mutex_unlock(&spicontext->spi_lock);
return ret;
}
/* As 2 bytes are already read */
len = 2;
/* Support of long frame */
if (receivebuff[0] & 0x60)
len += (((receivebuff[0] & 0x60) >> 5) << 8) | receivebuff[1];
else
len += receivebuff[1];
/* Now make a transfer to read only relevant bytes */
tx_takedata.rx_buf = &receivebuff[2];
tx_takedata.len = len - 2;
spi_message_init(&m);
spi_message_add_tail(&tx_takedata, &m);
ret = spi_sync(spidev, &m);
mutex_unlock(&spicontext->spi_lock);
if (ret) {
dev_err(&spidev->dev, "spi_recv_resp, data read error = %d\n",
ret);
return ret;
}
return len;
}
EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
unsigned char *receivebuff)
{
unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
struct spi_transfer t[2] = {
{.tx_buf = &readdata_cmd, .len = 1,},
{.rx_buf = receivebuff, .len = 1,},
};
struct spi_message m;
struct spi_device *spidev = spicontext->spidev;
int ret = 0;
mutex_lock(&spicontext->spi_lock);
spi_message_init(&m);
spi_message_add_tail(&t[0], &m);
spi_message_add_tail(&t[1], &m);
ret = spi_sync(spidev, &m);
mutex_unlock(&spicontext->spi_lock);
if (ret)
dev_err(&spidev->dev, "recv_echo_res, data read error = %d\n",
ret);
return ret;
}
EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);
/*
* ---------------------------------------------------------------------------
* drivers/nfc/st95hf/spi.h functions declarations for SPI communication
* ---------------------------------------------------------------------------
* Copyright (C) 2015 STMicroelectronics – All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LINUX_ST95HF_SPI_H
#define __LINUX_ST95HF_SPI_H
#include <linux/spi/spi.h>
/* Basic ST95HF SPI CMDs */
#define ST95HF_COMMAND_SEND 0x0
#define ST95HF_COMMAND_RESET 0x1
#define ST95HF_COMMAND_RECEIVE 0x2
#define ST95HF_RESET_CMD_LEN 0x1
/*
* structure to contain st95hf spi communication specific information.
* @req_issync: true for synchronous calls.
* @spidev: st95hf spi device object.
* @done: completion structure to wait for st95hf response
* for synchronous calls.
* @spi_lock: mutex to allow only one spi transfer at a time.
*/
struct st95hf_spi_context {
bool req_issync;
struct spi_device *spidev;
struct completion done;
struct mutex spi_lock;
};
/* flag to differentiate synchronous & asynchronous spi request */
enum req_type {
SYNC,
ASYNC,
};
int st95hf_spi_send(struct st95hf_spi_context *spicontext,
unsigned char *buffertx,
int datalen,
enum req_type reqtype);
int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
unsigned char *receivebuff);
int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
unsigned char *receivebuff);
#endif
......@@ -2139,7 +2139,7 @@ static int trf7970a_remove(struct spi_device *spi)
#ifdef CONFIG_PM_SLEEP
static int trf7970a_suspend(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
struct spi_device *spi = to_spi_device(dev);
struct trf7970a *trf = spi_get_drvdata(spi);
dev_dbg(dev, "Suspend\n");
......@@ -2155,7 +2155,7 @@ static int trf7970a_suspend(struct device *dev)
static int trf7970a_resume(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
struct spi_device *spi = to_spi_device(dev);
struct trf7970a *trf = spi_get_drvdata(spi);
int ret;
......@@ -2174,7 +2174,7 @@ static int trf7970a_resume(struct device *dev)
#ifdef CONFIG_PM
static int trf7970a_pm_runtime_suspend(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
struct spi_device *spi = to_spi_device(dev);
struct trf7970a *trf = spi_get_drvdata(spi);
int ret;
......@@ -2191,7 +2191,7 @@ static int trf7970a_pm_runtime_suspend(struct device *dev)
static int trf7970a_pm_runtime_resume(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
struct spi_device *spi = to_spi_device(dev);
struct trf7970a *trf = spi_get_drvdata(spi);
int ret;
......
/*
* Driver include for the PN544 NFC chip.
* Driver include for the Inside Secure microread NFC Chip.
*
* Copyright (C) 2011 Tieto Poland
* Copyright (C) 2012 Intel Corporation. All rights reserved.
......
......@@ -299,6 +299,7 @@ void nfc_driver_failure(struct nfc_dev *dev, int err);
int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
struct nfc_evt_transaction *evt_transaction);
int nfc_se_connectivity(struct nfc_dev *dev, u8 se_idx);
int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type);
int nfc_remove_se(struct nfc_dev *dev, u32 se_idx);
struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx);
......
......@@ -953,6 +953,19 @@ int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
}
EXPORT_SYMBOL(nfc_se_transaction);
int nfc_se_connectivity(struct nfc_dev *dev, u8 se_idx)
{
int rc;
pr_debug("connectivity: %x\n", se_idx);
device_lock(&dev->dev);
rc = nfc_genl_se_connectivity(dev, se_idx);
device_unlock(&dev->dev);
return rc;
}
EXPORT_SYMBOL(nfc_se_connectivity);
static void nfc_release(struct device *d)
{
struct nfc_dev *dev = to_nfc_dev(d);
......
......@@ -20,7 +20,8 @@
#include "digital.h"
#define DIGITAL_PROTO_NFCA_RF_TECH \
(NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK)
(NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | \
NFC_PROTO_NFC_DEP_MASK | NFC_PROTO_ISO14443_MASK)
#define DIGITAL_PROTO_NFCB_RF_TECH NFC_PROTO_ISO14443_B_MASK
......
......@@ -610,14 +610,14 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
struct nci_core_conn_create_cmd *cmd;
struct core_conn_create_data data;
if (!number_destination_params)
return -EINVAL;
data.length = params_len + sizeof(struct nci_core_conn_create_cmd);
cmd = kzalloc(data.length, GFP_KERNEL);
if (!cmd)
return -ENOMEM;
if (!number_destination_params)
return -EINVAL;
cmd->destination_type = destination_type;
cmd->number_destination_params = number_destination_params;
memcpy(cmd->params, params, params_len);
......
......@@ -676,7 +676,7 @@ int nci_hci_connect_gate(struct nci_dev *ndev,
break;
default:
pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
if (pipe < 0)
if (pipe == NCI_HCI_INVALID_PIPE)
return r;
pipe_created = true;
break;
......
......@@ -552,6 +552,43 @@ int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx,
return -EMSGSIZE;
}
int nfc_genl_se_connectivity(struct nfc_dev *dev, u8 se_idx)
{
struct nfc_se *se;
struct sk_buff *msg;
void *hdr;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
NFC_EVENT_SE_CONNECTIVITY);
if (!hdr)
goto free_msg;
se = nfc_find_se(dev, se_idx);
if (!se)
goto free_msg;
if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
nla_put_u32(msg, NFC_ATTR_SE_INDEX, se_idx) ||
nla_put_u8(msg, NFC_ATTR_SE_TYPE, se->type))
goto nla_put_failure;
genlmsg_end(msg, hdr);
genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
nla_put_failure:
genlmsg_cancel(msg, hdr);
free_msg:
nlmsg_free(msg);
return -EMSGSIZE;
}
static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
u32 portid, u32 seq,
struct netlink_callback *cb,
......
......@@ -105,6 +105,7 @@ int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type);
int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx);
int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx,
struct nfc_evt_transaction *evt_transaction);
int nfc_genl_se_connectivity(struct nfc_dev *dev, u8 se_idx);
struct nfc_dev *nfc_get_device(unsigned int idx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment