diff options
Diffstat (limited to 'drivers/nfc/st-nci')
-rw-r--r-- | drivers/nfc/st-nci/Kconfig | 18 | ||||
-rw-r--r-- | drivers/nfc/st-nci/i2c.c | 80 | ||||
-rw-r--r-- | drivers/nfc/st-nci/ndlc.c | 1 | ||||
-rw-r--r-- | drivers/nfc/st-nci/se.c | 3 | ||||
-rw-r--r-- | drivers/nfc/st-nci/spi.c | 81 |
5 files changed, 134 insertions, 49 deletions
diff --git a/drivers/nfc/st-nci/Kconfig b/drivers/nfc/st-nci/Kconfig index e7c6db9c5..dc9b777d7 100644 --- a/drivers/nfc/st-nci/Kconfig +++ b/drivers/nfc/st-nci/Kconfig @@ -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. diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c index 15e3ce2d2..8a56b5c6e 100644 --- a/drivers/nfc/st-nci/i2c.c +++ b/drivers/nfc/st-nci/i2c.c @@ -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"); diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c index 0884b1100..50880d747 100644 --- a/drivers/nfc/st-nci/ndlc.c +++ b/drivers/nfc/st-nci/ndlc.c @@ -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 diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c index dbab722a0..a53e5df80 100644 --- a/drivers/nfc/st-nci/se.c +++ b/drivers/nfc/st-nci/se.c @@ -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) { diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c index d6519bb9d..821dfa950 100644 --- a/drivers/nfc/st-nci/spi.c +++ b/drivers/nfc/st-nci/spi.c @@ -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"); |