]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/nfc/st21nfca/i2c.c
Merge tag 'cris-for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/jesper...
[karo-tx-linux.git] / drivers / nfc / st21nfca / i2c.c
index a98da33e680a462abb4623708c19346763f0dee3..1f44a151d20616b21a148b6d9d8b070d54089201 100644 (file)
 #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>
 
 #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");