diff options
Diffstat (limited to 'drivers/nfc/st21nfca/i2c.c')
-rw-r--r-- | drivers/nfc/st21nfca/i2c.c | 80 |
1 files changed, 60 insertions, 20 deletions
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index a98da33e680a..1f44a151d206 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -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"); |