mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-11 18:26:02 +00:00
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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWgsv0AAoJEIqAPN1PVmxKvukP/3eJwA+chAUF89/fqwqFTaJN fffLoOxx2OBIbTXD2VV36yw4bAo9tbKDAYBZiot3Ig7Kg0SeCJ5oPA9xCVnWPrEY hxFAldvl+lWQs8nrUOgUZItiFBeUPdfW9YX/yKhUZVc+602nUG/e/+6x8B5MhIce SAfgCyd0c16DApltP7sw1muyZMvsO6Ow6dyNzDUVYZuabvEhe3SLSj9KFJi7Thsp h41Iv+bwPLhwF4RXGA6rei/gdEDSMRohprdj3uTDiTarGW+OpcAO0zWACS5m4eR0 zF19+HjGPUk/LpFRaU31xX0ZQQjOTmmfsOt4FBb3P7oJx47egycsadLYPexeG7nj ruyS6ezlRX1I/tZsnyLNJK92mK5TXYLz2uJ8r2ii/BgPNE+AErB3zKCC+EjXzWhh AvClGu5b88WJLxoq3I3l5evPwGhebGZ8N/1uiFsHOxvzKVLgxwOmNLRGN4XXxB2i UbIHgBb6smsu/l+3q9R83kfoMaoWnr+OUIi2QPQVDt/K7t1LfsCuIhzcGSgo1VuW fGlA1iu+CNDknofeCl4JDo2UXAETO4gdKWw87GXeUcbbraLUczZeO7FFLZqxbMYc OCaPYshmVFeZRypYdRWDHw67ivj0/h+9iq4PP1XOROkRFH746dD/p4yamJwVi20B samZ8VPwzgH3/ohQJyX3 =VFUH -----END PGP SIGNATURE----- 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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
15ab90f400
50
Documentation/devicetree/bindings/net/nfc/st95hf.txt
Normal file
50
Documentation/devicetree/bindings/net/nfc/st95hf.txt
Normal file
@ -0,0 +1,50 @@
|
||||
* 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 @@ exit_irq_none:
|
||||
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 @@ err_dt:
|
||||
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,
|
||||
|
@ -1,19 +1,14 @@
|
||||
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>
|
||||
@ -34,18 +36,14 @@
|
||||
|
||||
/* ndlc header */
|
||||
#define ST_NCI_FRAME_HEADROOM 1
|
||||
#define ST_NCI_FRAME_TAILROOM 0
|
||||
#define ST_NCI_FRAME_TAILROOM 0
|
||||
|
||||
#define ST_NCI_SPI_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
|
||||
#define ST_NCI_SPI_MAX_SIZE 250 /* req 4.2.1 */
|
||||
|
||||
#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");
|
||||
|
@ -1,20 +1,15 @@
|
||||
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,7 +312,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
|
||||
|
||||
switch (event) {
|
||||
case ST21NFCA_EVT_CONNECTIVITY:
|
||||
break;
|
||||
r = nfc_se_connectivity(hdev->ndev, host);
|
||||
break;
|
||||
case ST21NFCA_EVT_TRANSACTION:
|
||||
/*
|
||||
* According to specification etsi 102 622
|
||||
@ -342,7 +343,7 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
|
||||
transaction->aid_len + 4, transaction->params_len);
|
||||
|
||||
r = nfc_se_transaction(hdev->ndev, host, transaction);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
nfc_err(&hdev->ndev->dev, "Unexpected event on connectivity gate\n");
|
||||
return 1;
|
||||
|
10
drivers/nfc/st95hf/Kconfig
Normal file
10
drivers/nfc/st95hf/Kconfig
Normal file
@ -0,0 +1,10 @@
|
||||
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.
|
6
drivers/nfc/st95hf/Makefile
Normal file
6
drivers/nfc/st95hf/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for STMicroelectronics NFC transceiver ST95HF
|
||||
#
|
||||
|
||||
obj-$(CONFIG_NFC_ST95HF) += st95hf.o
|
||||
st95hf-objs := spi.o core.o
|
1273
drivers/nfc/st95hf/core.c
Normal file
1273
drivers/nfc/st95hf/core.c
Normal file
File diff suppressed because it is too large
Load Diff
167
drivers/nfc/st95hf/spi.c
Normal file
167
drivers/nfc/st95hf/spi.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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);
|
64
drivers/nfc/st95hf/spi.h
Normal file
64
drivers/nfc/st95hf/spi.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* ---------------------------------------------------------------------------
|
||||
* 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;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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 @@ out:
|
||||
}
|
||||
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 @@ free_msg:
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user