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>steinar/wifi_calib_4_9_kernel
commit
15ab90f400
|
@ -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/net/nfc/
|
||||||
F: include/uapi/linux/nfc.h
|
F: include/uapi/linux/nfc.h
|
||||||
F: drivers/nfc/
|
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/pn544.h
|
||||||
|
F: include/linux/platform_data/st21nfca.h
|
||||||
|
F: include/linux/platform_data/st-nci.h
|
||||||
F: Documentation/devicetree/bindings/net/nfc/
|
F: Documentation/devicetree/bindings/net/nfc/
|
||||||
|
|
||||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||||
|
|
|
@ -76,4 +76,5 @@ source "drivers/nfc/st21nfca/Kconfig"
|
||||||
source "drivers/nfc/st-nci/Kconfig"
|
source "drivers/nfc/st-nci/Kconfig"
|
||||||
source "drivers/nfc/nxp-nci/Kconfig"
|
source "drivers/nfc/nxp-nci/Kconfig"
|
||||||
source "drivers/nfc/s3fwrn5/Kconfig"
|
source "drivers/nfc/s3fwrn5/Kconfig"
|
||||||
|
source "drivers/nfc/st95hf/Kconfig"
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -16,3 +16,4 @@ obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
|
||||||
obj-$(CONFIG_NFC_ST_NCI) += st-nci/
|
obj-$(CONFIG_NFC_ST_NCI) += st-nci/
|
||||||
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/
|
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/
|
||||||
obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5/
|
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;
|
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),
|
phy = devm_kzalloc(dev, sizeof(struct fdp_i2c_phy),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!phy)
|
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;
|
phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;
|
||||||
i2c_set_clientdata(client, phy);
|
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,
|
r = request_threaded_irq(client->irq, NULL, fdp_nci_i2c_irq_thread_fn,
|
||||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||||
FDP_I2C_DRIVER_NAME, phy);
|
FDP_I2C_DRIVER_NAME, phy);
|
||||||
|
|
|
@ -50,8 +50,6 @@ struct microread_i2c_phy {
|
||||||
struct i2c_client *i2c_dev;
|
struct i2c_client *i2c_dev;
|
||||||
struct nfc_hci_dev *hdev;
|
struct nfc_hci_dev *hdev;
|
||||||
|
|
||||||
int irq;
|
|
||||||
|
|
||||||
int hard_fault; /*
|
int hard_fault; /*
|
||||||
* < 0 if hardware error occured (e.g. i2c err)
|
* < 0 if hardware error occured (e.g. i2c err)
|
||||||
* and prevents normal operation.
|
* and prevents normal operation.
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#define NFCSIM_POLL_TARGET 2
|
#define NFCSIM_POLL_TARGET 2
|
||||||
#define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET)
|
#define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET)
|
||||||
|
|
||||||
|
#define RX_DEFAULT_DELAY 5
|
||||||
|
|
||||||
struct nfcsim {
|
struct nfcsim {
|
||||||
struct nfc_dev *nfc_dev;
|
struct nfc_dev *nfc_dev;
|
||||||
|
|
||||||
|
@ -51,6 +53,8 @@ struct nfcsim {
|
||||||
|
|
||||||
u8 initiator;
|
u8 initiator;
|
||||||
|
|
||||||
|
u32 rx_delay;
|
||||||
|
|
||||||
data_exchange_cb_t cb;
|
data_exchange_cb_t cb;
|
||||||
void *cb_context;
|
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
|
* If packet transmission occurs immediately between them, we have a
|
||||||
* non-stop flow of several tens of thousands SYMM packets per second
|
* non-stop flow of several tens of thousands SYMM packets per second
|
||||||
* and a burning cpu.
|
* 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);
|
mutex_unlock(&peer->lock);
|
||||||
|
|
||||||
|
@ -461,6 +464,7 @@ static struct nfcsim *nfcsim_init_dev(void)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto free_nfc_dev;
|
goto free_nfc_dev;
|
||||||
|
|
||||||
|
dev->rx_delay = RX_DEFAULT_DELAY;
|
||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
free_nfc_dev:
|
free_nfc_dev:
|
||||||
|
|
|
@ -52,7 +52,6 @@ struct nxp_nci_i2c_phy {
|
||||||
|
|
||||||
unsigned int gpio_en;
|
unsigned int gpio_en;
|
||||||
unsigned int gpio_fw;
|
unsigned int gpio_fw;
|
||||||
unsigned int gpio_irq;
|
|
||||||
|
|
||||||
int hard_fault; /*
|
int hard_fault; /*
|
||||||
* < 0 if hardware error occurred (e.g. i2c err)
|
* < 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;
|
return phy->hard_fault;
|
||||||
|
|
||||||
r = i2c_master_send(client, skb->data, skb->len);
|
r = i2c_master_send(client, skb->data, skb->len);
|
||||||
if (r == -EREMOTEIO) {
|
if (r < 0) {
|
||||||
/* Retry, chip was in standby */
|
/* Retry, chip was in standby */
|
||||||
usleep_range(110000, 120000);
|
usleep_range(110000, 120000);
|
||||||
r = i2c_master_send(client, skb->data, skb->len);
|
r = i2c_master_send(client, skb->data, skb->len);
|
||||||
|
@ -264,8 +263,6 @@ exit_irq_none:
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
|
||||||
|
|
||||||
static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
|
static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(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;
|
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;
|
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)
|
static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = phy->i2c_dev;
|
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_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_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");
|
nfc_err(&client->dev, "No GPIOs\n");
|
||||||
return -EINVAL;
|
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_en = desc_to_gpio(gpiod_en);
|
||||||
phy->gpio_fw = desc_to_gpio(gpiod_fw);
|
phy->gpio_fw = desc_to_gpio(gpiod_fw);
|
||||||
phy->gpio_irq = desc_to_gpio(gpiod_irq);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -374,7 +347,6 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
|
||||||
} else if (pdata) {
|
} else if (pdata) {
|
||||||
phy->gpio_en = pdata->gpio_en;
|
phy->gpio_en = pdata->gpio_en;
|
||||||
phy->gpio_fw = pdata->gpio_fw;
|
phy->gpio_fw = pdata->gpio_fw;
|
||||||
client->irq = pdata->irq;
|
|
||||||
} else if (ACPI_HANDLE(&client->dev)) {
|
} else if (ACPI_HANDLE(&client->dev)) {
|
||||||
r = nxp_nci_i2c_acpi_config(phy);
|
r = nxp_nci_i2c_acpi_config(phy);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -166,7 +166,6 @@ struct pn544_i2c_phy {
|
||||||
struct nfc_hci_dev *hdev;
|
struct nfc_hci_dev *hdev;
|
||||||
|
|
||||||
unsigned int gpio_en;
|
unsigned int gpio_en;
|
||||||
unsigned int gpio_irq;
|
|
||||||
unsigned int gpio_fw;
|
unsigned int gpio_fw;
|
||||||
unsigned int en_polarity;
|
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);
|
struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
|
||||||
const struct acpi_device_id *id;
|
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;
|
struct device *dev;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!client)
|
if (!client)
|
||||||
return -EINVAL;
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
|
||||||
|
|
||||||
static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
|
static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct pn544_i2c_phy *phy = i2c_get_clientdata(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;
|
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;
|
return 0;
|
||||||
|
|
||||||
err_gpio_fw:
|
err_gpio_fw:
|
||||||
|
@ -1015,15 +981,6 @@ err_dt:
|
||||||
return ret;
|
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,
|
static int pn544_hci_i2c_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
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_en = pdata->get_gpio(NFC_GPIO_ENABLE);
|
||||||
phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
|
phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
|
||||||
phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
|
|
||||||
/* Using ACPI */
|
/* Using ACPI */
|
||||||
} else if (ACPI_HANDLE(&client->dev)) {
|
} else if (ACPI_HANDLE(&client->dev)) {
|
||||||
r = pn544_hci_i2c_acpi_request_resources(client);
|
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,
|
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;
|
struct s3fwrn5_info *info;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -125,7 +125,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
|
||||||
return 0;
|
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_wake = s3fwrn5_i2c_set_wake,
|
||||||
.set_mode = s3fwrn5_i2c_set_mode,
|
.set_mode = s3fwrn5_i2c_set_mode,
|
||||||
.get_mode = s3fwrn5_i2c_get_mode,
|
.get_mode = s3fwrn5_i2c_get_mode,
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct s3fwrn5_info {
|
||||||
void *phy_id;
|
void *phy_id;
|
||||||
struct device *pdev;
|
struct device *pdev;
|
||||||
|
|
||||||
struct s3fwrn5_phy_ops *phy_ops;
|
const struct s3fwrn5_phy_ops *phy_ops;
|
||||||
unsigned int max_payload;
|
unsigned int max_payload;
|
||||||
|
|
||||||
struct s3fwrn5_fw_info fw_info;
|
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,
|
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);
|
void s3fwrn5_remove(struct nci_dev *ndev);
|
||||||
|
|
||||||
int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
|
int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
config NFC_ST_NCI
|
config NFC_ST_NCI
|
||||||
tristate "STMicroelectronics ST NCI NFC driver"
|
tristate
|
||||||
depends on NFC_NCI
|
|
||||||
default n
|
|
||||||
---help---
|
---help---
|
||||||
STMicroelectronics NFC NCI chips core driver. It implements the chipset
|
STMicroelectronics NFC NCI chips core driver. It implements the chipset
|
||||||
NCI logic and hooks into the NFC kernel APIs. Physical layers will
|
NCI logic and hooks into the NFC kernel APIs. Physical layers will
|
||||||
register against it.
|
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
|
config NFC_ST_NCI_I2C
|
||||||
tristate "NFC ST NCI i2c support"
|
tristate "STMicroelectronics ST NCI NFC driver (I2C)"
|
||||||
depends on NFC_ST_NCI && I2C
|
depends on NFC_NCI && I2C
|
||||||
|
select NFC_ST_NCI
|
||||||
---help---
|
---help---
|
||||||
This module adds support for an I2C interface to the
|
This module adds support for an I2C interface to the
|
||||||
STMicroelectronics NFC NCI chips familly.
|
STMicroelectronics NFC NCI chips familly.
|
||||||
|
@ -23,8 +18,9 @@ config NFC_ST_NCI_I2C
|
||||||
Say N if unsure.
|
Say N if unsure.
|
||||||
|
|
||||||
config NFC_ST_NCI_SPI
|
config NFC_ST_NCI_SPI
|
||||||
tristate "NFC ST NCI spi support"
|
tristate "STMicroelectronics ST NCI NFC driver (SPI)"
|
||||||
depends on NFC_ST_NCI && SPI
|
depends on NFC_NCI && SPI
|
||||||
|
select NFC_ST_NCI
|
||||||
---help---
|
---help---
|
||||||
This module adds support for an SPI interface to the
|
This module adds support for an SPI interface to the
|
||||||
STMicroelectronics NFC NCI chips familly.
|
STMicroelectronics NFC NCI chips familly.
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/nfc.h>
|
#include <linux/nfc.h>
|
||||||
|
@ -40,11 +42,7 @@
|
||||||
|
|
||||||
#define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c"
|
#define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c"
|
||||||
|
|
||||||
static struct i2c_device_id st_nci_i2c_id_table[] = {
|
#define ST_NCI_GPIO_NAME_RESET "clf_reset"
|
||||||
{ST_NCI_DRIVER_NAME, 0},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table);
|
|
||||||
|
|
||||||
struct st_nci_i2c_phy {
|
struct st_nci_i2c_phy {
|
||||||
struct i2c_client *i2c_dev;
|
struct i2c_client *i2c_dev;
|
||||||
|
@ -210,7 +208,43 @@ static struct nfc_phy_ops i2c_phy_ops = {
|
||||||
.disable = st_nci_i2c_disable,
|
.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)
|
static int st_nci_i2c_of_request_resources(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct st_nci_i2c_phy *phy = i2c_get_clientdata(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 */
|
/* GPIO request and configuration */
|
||||||
r = devm_gpio_request_one(&client->dev, gpio,
|
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) {
|
if (r) {
|
||||||
nfc_err(&client->dev, "Failed to request reset pin\n");
|
nfc_err(&client->dev, "Failed to request reset pin\n");
|
||||||
return r;
|
return r;
|
||||||
|
@ -248,12 +282,6 @@ static int st_nci_i2c_of_request_resources(struct i2c_client *client)
|
||||||
|
|
||||||
return 0;
|
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)
|
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;
|
phy->irq_polarity = pdata->irq_polarity;
|
||||||
|
|
||||||
r = devm_gpio_request_one(&client->dev,
|
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) {
|
if (r) {
|
||||||
pr_err("%s : reset gpio_request failed\n", __FILE__);
|
pr_err("%s : reset gpio_request failed\n", __FILE__);
|
||||||
return r;
|
return r;
|
||||||
|
@ -322,6 +351,12 @@ static int st_nci_i2c_probe(struct i2c_client *client,
|
||||||
"Cannot get platform resources\n");
|
"Cannot get platform resources\n");
|
||||||
return r;
|
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 {
|
} else {
|
||||||
nfc_err(&client->dev,
|
nfc_err(&client->dev,
|
||||||
"st_nci platform resources not available\n");
|
"st_nci platform resources not available\n");
|
||||||
|
@ -358,7 +393,19 @@ static int st_nci_i2c_remove(struct i2c_client *client)
|
||||||
return 0;
|
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[] = {
|
static const struct of_device_id of_st_nci_i2c_match[] = {
|
||||||
{ .compatible = "st,st21nfcb-i2c", },
|
{ .compatible = "st,st21nfcb-i2c", },
|
||||||
{ .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);
|
MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match);
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct i2c_driver st_nci_i2c_driver = {
|
static struct i2c_driver st_nci_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = ST_NCI_I2C_DRIVER_NAME,
|
.name = ST_NCI_I2C_DRIVER_NAME,
|
||||||
.of_match_table = of_match_ptr(of_st_nci_i2c_match),
|
.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,
|
.probe = st_nci_i2c_probe,
|
||||||
.id_table = st_nci_i2c_id_table,
|
.id_table = st_nci_i2c_id_table,
|
||||||
.remove = st_nci_i2c_remove,
|
.remove = st_nci_i2c_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_i2c_driver(st_nci_i2c_driver);
|
module_i2c_driver(st_nci_i2c_driver);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <net/nfc/nci_core.h>
|
#include <net/nfc/nci_core.h>
|
||||||
|
|
||||||
#include "st-nci.h"
|
#include "st-nci.h"
|
||||||
#include "ndlc.h"
|
|
||||||
|
|
||||||
#define NDLC_TIMER_T1 100
|
#define NDLC_TIMER_T1 100
|
||||||
#define NDLC_TIMER_T1_WAIT 400
|
#define NDLC_TIMER_T1_WAIT 400
|
||||||
|
|
|
@ -331,7 +331,7 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case ST_NCI_EVT_CONNECTIVITY:
|
case ST_NCI_EVT_CONNECTIVITY:
|
||||||
|
r = nfc_se_connectivity(ndev->nfc_dev, host);
|
||||||
break;
|
break;
|
||||||
case ST_NCI_EVT_TRANSACTION:
|
case ST_NCI_EVT_TRANSACTION:
|
||||||
/* According to specification etsi 102 622
|
/* 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);
|
EXPORT_SYMBOL_GPL(st_nci_hci_event_received);
|
||||||
|
|
||||||
|
|
||||||
void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
|
void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/nfc.h>
|
#include <linux/nfc.h>
|
||||||
|
@ -41,11 +43,7 @@
|
||||||
|
|
||||||
#define ST_NCI_SPI_DRIVER_NAME "st_nci_spi"
|
#define ST_NCI_SPI_DRIVER_NAME "st_nci_spi"
|
||||||
|
|
||||||
static struct spi_device_id st_nci_spi_id_table[] = {
|
#define ST_NCI_GPIO_NAME_RESET "clf_reset"
|
||||||
{ST_NCI_SPI_DRIVER_NAME, 0},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
|
|
||||||
|
|
||||||
struct st_nci_spi_phy {
|
struct st_nci_spi_phy {
|
||||||
struct spi_device *spi_dev;
|
struct spi_device *spi_dev;
|
||||||
|
@ -225,7 +223,43 @@ static struct nfc_phy_ops spi_phy_ops = {
|
||||||
.disable = st_nci_spi_disable,
|
.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)
|
static int st_nci_spi_of_request_resources(struct spi_device *dev)
|
||||||
{
|
{
|
||||||
struct st_nci_spi_phy *phy = spi_get_drvdata(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 */
|
/* GPIO request and configuration */
|
||||||
r = devm_gpio_request_one(&dev->dev, gpio,
|
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) {
|
if (r) {
|
||||||
nfc_err(&dev->dev, "Failed to request reset pin\n");
|
nfc_err(&dev->dev, "Failed to request reset pin\n");
|
||||||
return r;
|
return r;
|
||||||
|
@ -263,12 +297,6 @@ static int st_nci_spi_of_request_resources(struct spi_device *dev)
|
||||||
|
|
||||||
return 0;
|
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)
|
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;
|
phy->irq_polarity = pdata->irq_polarity;
|
||||||
|
|
||||||
r = devm_gpio_request_one(&dev->dev,
|
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) {
|
if (r) {
|
||||||
pr_err("%s : reset gpio_request failed\n", __FILE__);
|
pr_err("%s : reset gpio_request failed\n", __FILE__);
|
||||||
return r;
|
return r;
|
||||||
|
@ -338,6 +367,12 @@ static int st_nci_spi_probe(struct spi_device *dev)
|
||||||
"Cannot get platform resources\n");
|
"Cannot get platform resources\n");
|
||||||
return r;
|
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 {
|
} else {
|
||||||
nfc_err(&dev->dev,
|
nfc_err(&dev->dev,
|
||||||
"st_nci platform resources not available\n");
|
"st_nci platform resources not available\n");
|
||||||
|
@ -374,24 +409,34 @@ static int st_nci_spi_remove(struct spi_device *dev)
|
||||||
return 0;
|
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[] = {
|
static const struct of_device_id of_st_nci_spi_match[] = {
|
||||||
{ .compatible = "st,st21nfcb-spi", },
|
{ .compatible = "st,st21nfcb-spi", },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
|
MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct spi_driver st_nci_spi_driver = {
|
static struct spi_driver st_nci_spi_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = ST_NCI_SPI_DRIVER_NAME,
|
.name = ST_NCI_SPI_DRIVER_NAME,
|
||||||
.of_match_table = of_match_ptr(of_st_nci_spi_match),
|
.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,
|
.probe = st_nci_spi_probe,
|
||||||
.id_table = st_nci_spi_id_table,
|
.id_table = st_nci_spi_id_table,
|
||||||
.remove = st_nci_spi_remove,
|
.remove = st_nci_spi_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_spi_driver(st_nci_spi_driver);
|
module_spi_driver(st_nci_spi_driver);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
config NFC_ST21NFCA
|
config NFC_ST21NFCA
|
||||||
tristate "STMicroelectronics ST21NFCA NFC driver"
|
tristate
|
||||||
depends on NFC_HCI
|
|
||||||
select CRC_CCITT
|
select CRC_CCITT
|
||||||
default n
|
|
||||||
---help---
|
---help---
|
||||||
STMicroelectronics ST21NFCA core driver. It implements the chipset
|
STMicroelectronics ST21NFCA core driver. It implements the chipset
|
||||||
HCI logic and hooks into the NFC kernel APIs. Physical layers will
|
HCI logic and hooks into the NFC kernel APIs. Physical layers will
|
||||||
register against it.
|
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
|
config NFC_ST21NFCA_I2C
|
||||||
tristate "NFC ST21NFCA i2c support"
|
tristate "STMicroelectronics ST21NFCA NFC driver (I2C)"
|
||||||
depends on NFC_ST21NFCA && I2C && NFC_SHDLC
|
depends on NFC_HCI && I2C && NFC_SHDLC
|
||||||
|
select NFC_ST21NFCA
|
||||||
---help---
|
---help---
|
||||||
This module adds support for the STMicroelectronics st21nfca i2c interface.
|
This module adds support for the STMicroelectronics st21nfca i2c interface.
|
||||||
Select this if your platform is using the i2c bus.
|
Select this if your platform is using the i2c bus.
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
@ -60,12 +62,7 @@
|
||||||
|
|
||||||
#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"
|
#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"
|
||||||
|
|
||||||
static struct i2c_device_id st21nfca_hci_i2c_id_table[] = {
|
#define ST21NFCA_GPIO_NAME_EN "clf_enable"
|
||||||
{ST21NFCA_HCI_DRIVER_NAME, 0},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table);
|
|
||||||
|
|
||||||
struct st21nfca_i2c_phy {
|
struct st21nfca_i2c_phy {
|
||||||
struct i2c_client *i2c_dev;
|
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;
|
struct st21nfca_i2c_phy *phy = phy_id;
|
||||||
|
|
||||||
pr_info("\n");
|
|
||||||
gpio_set_value(phy->gpio_ena, 0);
|
gpio_set_value(phy->gpio_ena, 0);
|
||||||
|
|
||||||
phy->powered = 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);
|
I2C_DUMP_SKB("st21nfca_hci_i2c_write", skb);
|
||||||
|
|
||||||
|
|
||||||
if (phy->hard_fault != 0)
|
if (phy->hard_fault != 0)
|
||||||
return phy->hard_fault;
|
return phy->hard_fault;
|
||||||
|
|
||||||
|
@ -509,7 +504,41 @@ static struct nfc_phy_ops i2c_phy_ops = {
|
||||||
.disable = st21nfca_hci_i2c_disable,
|
.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)
|
static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(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 */
|
/* GPIO request and configuration */
|
||||||
r = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH,
|
r = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH,
|
||||||
"clf_enable");
|
ST21NFCA_GPIO_NAME_EN);
|
||||||
if (r) {
|
if (r) {
|
||||||
nfc_err(&client->dev, "Failed to request enable pin\n");
|
nfc_err(&client->dev, "Failed to request enable pin\n");
|
||||||
return r;
|
return r;
|
||||||
|
@ -547,12 +576,6 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
|
||||||
|
|
||||||
return 0;
|
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)
|
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) {
|
if (phy->gpio_ena > 0) {
|
||||||
r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
|
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) {
|
if (r) {
|
||||||
pr_err("%s : ena gpio_request failed\n", __FILE__);
|
pr_err("%s : ena gpio_request failed\n", __FILE__);
|
||||||
return r;
|
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");
|
nfc_err(&client->dev, "Cannot get platform resources\n");
|
||||||
return r;
|
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 {
|
} else {
|
||||||
nfc_err(&client->dev, "st21nfca platform resources not available\n");
|
nfc_err(&client->dev, "st21nfca platform resources not available\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -670,26 +700,36 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client)
|
||||||
return 0;
|
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[] = {
|
static const struct of_device_id of_st21nfca_i2c_match[] = {
|
||||||
{ .compatible = "st,st21nfca-i2c", },
|
{ .compatible = "st,st21nfca-i2c", },
|
||||||
{ .compatible = "st,st21nfca_i2c", },
|
{ .compatible = "st,st21nfca_i2c", },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
|
MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct i2c_driver st21nfca_hci_i2c_driver = {
|
static struct i2c_driver st21nfca_hci_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = ST21NFCA_HCI_I2C_DRIVER_NAME,
|
.name = ST21NFCA_HCI_I2C_DRIVER_NAME,
|
||||||
.of_match_table = of_match_ptr(of_st21nfca_i2c_match),
|
.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,
|
.probe = st21nfca_hci_i2c_probe,
|
||||||
.id_table = st21nfca_hci_i2c_id_table,
|
.id_table = st21nfca_hci_i2c_id_table,
|
||||||
.remove = st21nfca_hci_i2c_remove,
|
.remove = st21nfca_hci_i2c_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_i2c_driver(st21nfca_hci_i2c_driver);
|
module_i2c_driver(st21nfca_hci_i2c_driver);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -312,6 +312,7 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case ST21NFCA_EVT_CONNECTIVITY:
|
case ST21NFCA_EVT_CONNECTIVITY:
|
||||||
|
r = nfc_se_connectivity(hdev->ndev, host);
|
||||||
break;
|
break;
|
||||||
case ST21NFCA_EVT_TRANSACTION:
|
case ST21NFCA_EVT_TRANSACTION:
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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.
|
|
@ -0,0 +1,6 @@
|
||||||
|
#
|
||||||
|
# Makefile for STMicroelectronics NFC transceiver ST95HF
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_NFC_ST95HF) += st95hf.o
|
||||||
|
st95hf-objs := spi.o core.o
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
|
@ -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
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int trf7970a_suspend(struct device *dev)
|
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);
|
struct trf7970a *trf = spi_get_drvdata(spi);
|
||||||
|
|
||||||
dev_dbg(dev, "Suspend\n");
|
dev_dbg(dev, "Suspend\n");
|
||||||
|
@ -2155,7 +2155,7 @@ static int trf7970a_suspend(struct device *dev)
|
||||||
|
|
||||||
static int trf7970a_resume(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);
|
struct trf7970a *trf = spi_get_drvdata(spi);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -2174,7 +2174,7 @@ static int trf7970a_resume(struct device *dev)
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int trf7970a_pm_runtime_suspend(struct device *dev)
|
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);
|
struct trf7970a *trf = spi_get_drvdata(spi);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -2191,7 +2191,7 @@ static int trf7970a_pm_runtime_suspend(struct device *dev)
|
||||||
|
|
||||||
static int trf7970a_pm_runtime_resume(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);
|
struct trf7970a *trf = spi_get_drvdata(spi);
|
||||||
int ret;
|
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) 2011 Tieto Poland
|
||||||
* Copyright (C) 2012 Intel Corporation. All rights reserved.
|
* 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,
|
int nfc_se_transaction(struct nfc_dev *dev, u8 se_idx,
|
||||||
struct nfc_evt_transaction *evt_transaction);
|
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_add_se(struct nfc_dev *dev, u32 se_idx, u16 type);
|
||||||
int nfc_remove_se(struct nfc_dev *dev, u32 se_idx);
|
int nfc_remove_se(struct nfc_dev *dev, u32 se_idx);
|
||||||
struct nfc_se *nfc_find_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);
|
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)
|
static void nfc_release(struct device *d)
|
||||||
{
|
{
|
||||||
struct nfc_dev *dev = to_nfc_dev(d);
|
struct nfc_dev *dev = to_nfc_dev(d);
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
#include "digital.h"
|
#include "digital.h"
|
||||||
|
|
||||||
#define DIGITAL_PROTO_NFCA_RF_TECH \
|
#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
|
#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 nci_core_conn_create_cmd *cmd;
|
||||||
struct core_conn_create_data data;
|
struct core_conn_create_data data;
|
||||||
|
|
||||||
|
if (!number_destination_params)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
data.length = params_len + sizeof(struct nci_core_conn_create_cmd);
|
data.length = params_len + sizeof(struct nci_core_conn_create_cmd);
|
||||||
cmd = kzalloc(data.length, GFP_KERNEL);
|
cmd = kzalloc(data.length, GFP_KERNEL);
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (!number_destination_params)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
cmd->destination_type = destination_type;
|
cmd->destination_type = destination_type;
|
||||||
cmd->number_destination_params = number_destination_params;
|
cmd->number_destination_params = number_destination_params;
|
||||||
memcpy(cmd->params, params, params_len);
|
memcpy(cmd->params, params, params_len);
|
||||||
|
|
|
@ -676,7 +676,7 @@ int nci_hci_connect_gate(struct nci_dev *ndev,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
|
pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
|
||||||
if (pipe < 0)
|
if (pipe == NCI_HCI_INVALID_PIPE)
|
||||||
return r;
|
return r;
|
||||||
pipe_created = true;
|
pipe_created = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -552,6 +552,43 @@ free_msg:
|
||||||
return -EMSGSIZE;
|
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,
|
static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
|
||||||
u32 portid, u32 seq,
|
u32 portid, u32 seq,
|
||||||
struct netlink_callback *cb,
|
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_removed(struct nfc_dev *dev, u32 se_idx);
|
||||||
int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx,
|
int nfc_genl_se_transaction(struct nfc_dev *dev, u8 se_idx,
|
||||||
struct nfc_evt_transaction *evt_transaction);
|
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);
|
struct nfc_dev *nfc_get_device(unsigned int idx);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue