#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;
{
struct st21nfca_i2c_phy *phy = phy_id;
- pr_info("\n");
gpio_set_value(phy->gpio_ena, 0);
phy->powered = 0;
I2C_DUMP_SKB("st21nfca_hci_i2c_write", skb);
-
if (phy->hard_fault != 0)
return phy->hard_fault;
.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);
/* 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;
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)
{
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;
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;
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");