diff options
| author | Robert Dolca <robert.dolca@intel.com> | 2015-01-26 06:13:37 -0500 |
|---|---|---|
| committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-01-27 19:09:08 -0500 |
| commit | 0a5942c8e1480db4b8ee7a8d643e4945ef2f8fed (patch) | |
| tree | f950d6119efca2ee54835c6af32827e9e5c516c4 | |
| parent | 75dda421a31dc614b8b6502cafd3825e2c72ccf0 (diff) | |
NFC: Add ACPI support for NXP PN544
Currently there is no support for ACPI.
This patch uses the following configuration:
- Device id: NXP5440
- Pin mapping:
- 0 IRQ pin
- 1 enable pin
- 2 firmware pin
Signed-off-by: Robert Dolca <robert.dolca@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
| -rw-r--r-- | drivers/nfc/pn544/i2c.c | 111 |
1 files changed, 109 insertions, 2 deletions
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index d9018cda6c7f..cdde745b96bd 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c | |||
| @@ -24,11 +24,13 @@ | |||
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 25 | #include <linux/of_gpio.h> | 25 | #include <linux/of_gpio.h> |
| 26 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
| 27 | #include <linux/acpi.h> | ||
| 27 | #include <linux/miscdevice.h> | 28 | #include <linux/miscdevice.h> |
| 28 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| 29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 30 | #include <linux/nfc.h> | 31 | #include <linux/nfc.h> |
| 31 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
| 33 | #include <linux/gpio/consumer.h> | ||
| 32 | #include <linux/platform_data/pn544.h> | 34 | #include <linux/platform_data/pn544.h> |
| 33 | #include <asm/unaligned.h> | 35 | #include <asm/unaligned.h> |
| 34 | 36 | ||
| @@ -41,6 +43,11 @@ | |||
| 41 | #define PN544_I2C_FRAME_HEADROOM 1 | 43 | #define PN544_I2C_FRAME_HEADROOM 1 |
| 42 | #define PN544_I2C_FRAME_TAILROOM 2 | 44 | #define PN544_I2C_FRAME_TAILROOM 2 |
| 43 | 45 | ||
| 46 | /* GPIO names */ | ||
| 47 | #define PN544_GPIO_NAME_IRQ "pn544_irq" | ||
| 48 | #define PN544_GPIO_NAME_FW "pn544_fw" | ||
| 49 | #define PN544_GPIO_NAME_EN "pn544_en" | ||
| 50 | |||
| 44 | /* framing in HCI mode */ | 51 | /* framing in HCI mode */ |
| 45 | #define PN544_HCI_I2C_LLC_LEN 1 | 52 | #define PN544_HCI_I2C_LLC_LEN 1 |
| 46 | #define PN544_HCI_I2C_LLC_CRC 2 | 53 | #define PN544_HCI_I2C_LLC_CRC 2 |
| @@ -58,6 +65,13 @@ static struct i2c_device_id pn544_hci_i2c_id_table[] = { | |||
| 58 | 65 | ||
| 59 | MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); | 66 | MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); |
| 60 | 67 | ||
| 68 | static const struct acpi_device_id pn544_hci_i2c_acpi_match[] = { | ||
| 69 | {"NXP5440", 0}, | ||
| 70 | {} | ||
| 71 | }; | ||
| 72 | |||
| 73 | MODULE_DEVICE_TABLE(acpi, pn544_hci_i2c_acpi_match); | ||
| 74 | |||
| 61 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" | 75 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" |
| 62 | 76 | ||
| 63 | /* | 77 | /* |
| @@ -861,6 +875,90 @@ exit_state_wait_secure_write_answer: | |||
| 861 | } | 875 | } |
| 862 | } | 876 | } |
| 863 | 877 | ||
| 878 | static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client) | ||
| 879 | { | ||
| 880 | struct pn544_i2c_phy *phy = i2c_get_clientdata(client); | ||
| 881 | const struct acpi_device_id *id; | ||
| 882 | struct gpio_desc *gpiod_en, *gpiod_irq, *gpiod_fw; | ||
| 883 | struct device *dev; | ||
| 884 | int ret; | ||
| 885 | |||
| 886 | if (!client) | ||
| 887 | return -EINVAL; | ||
| 888 | |||
| 889 | dev = &client->dev; | ||
| 890 | |||
| 891 | /* Match the struct device against a given list of ACPI IDs */ | ||
| 892 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 893 | |||
| 894 | if (!id) | ||
| 895 | return -ENODEV; | ||
| 896 | |||
| 897 | /* Get EN GPIO from ACPI */ | ||
| 898 | gpiod_en = devm_gpiod_get_index(dev, PN544_GPIO_NAME_EN, 1); | ||
| 899 | if (IS_ERR(gpiod_en)) { | ||
| 900 | nfc_err(dev, | ||
| 901 | "Unable to get EN GPIO\n"); | ||
| 902 | return -ENODEV; | ||
| 903 | } | ||
| 904 | |||
| 905 | phy->gpio_en = desc_to_gpio(gpiod_en); | ||
| 906 | |||
| 907 | /* Configuration EN GPIO */ | ||
| 908 | ret = gpiod_direction_output(gpiod_en, 0); | ||
| 909 | if (ret) { | ||
| 910 | nfc_err(dev, "Fail EN pin direction\n"); | ||
| 911 | return ret; | ||
| 912 | } | ||
| 913 | |||
| 914 | /* Get FW GPIO from ACPI */ | ||
| 915 | gpiod_fw = devm_gpiod_get_index(dev, PN544_GPIO_NAME_FW, 2); | ||
| 916 | if (IS_ERR(gpiod_fw)) { | ||
| 917 | nfc_err(dev, | ||
| 918 | "Unable to get FW GPIO\n"); | ||
| 919 | return -ENODEV; | ||
| 920 | } | ||
| 921 | |||
| 922 | phy->gpio_fw = desc_to_gpio(gpiod_fw); | ||
| 923 | |||
| 924 | /* Configuration FW GPIO */ | ||
| 925 | ret = gpiod_direction_output(gpiod_fw, 0); | ||
| 926 | if (ret) { | ||
| 927 | nfc_err(dev, "Fail FW pin direction\n"); | ||
| 928 | return ret; | ||
| 929 | } | ||
| 930 | |||
| 931 | /* Get IRQ GPIO */ | ||
| 932 | gpiod_irq = devm_gpiod_get_index(dev, PN544_GPIO_NAME_IRQ, 0); | ||
| 933 | if (IS_ERR(gpiod_irq)) { | ||
| 934 | nfc_err(dev, | ||
| 935 | "Unable to get IRQ GPIO\n"); | ||
| 936 | return -ENODEV; | ||
| 937 | } | ||
| 938 | |||
| 939 | phy->gpio_irq = desc_to_gpio(gpiod_irq); | ||
| 940 | |||
| 941 | /* Configure IRQ GPIO */ | ||
| 942 | ret = gpiod_direction_input(gpiod_irq); | ||
| 943 | if (ret) { | ||
| 944 | nfc_err(dev, "Fail IRQ pin direction\n"); | ||
| 945 | return ret; | ||
| 946 | } | ||
| 947 | |||
| 948 | /* Map the pin to an IRQ */ | ||
| 949 | ret = gpiod_to_irq(gpiod_irq); | ||
| 950 | if (ret < 0) { | ||
| 951 | nfc_err(dev, "Fail pin IRQ mapping\n"); | ||
| 952 | return ret; | ||
| 953 | } | ||
| 954 | |||
| 955 | nfc_info(dev, "GPIO resource, no:%d irq:%d\n", | ||
| 956 | desc_to_gpio(gpiod_irq), ret); | ||
| 957 | client->irq = ret; | ||
| 958 | |||
| 959 | return 0; | ||
| 960 | } | ||
| 961 | |||
| 864 | #ifdef CONFIG_OF | 962 | #ifdef CONFIG_OF |
| 865 | 963 | ||
| 866 | static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | 964 | static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) |
| @@ -886,7 +984,7 @@ static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | |||
| 886 | phy->gpio_en = ret; | 984 | phy->gpio_en = ret; |
| 887 | 985 | ||
| 888 | /* Configuration of EN GPIO */ | 986 | /* Configuration of EN GPIO */ |
| 889 | ret = gpio_request(phy->gpio_en, "pn544_en"); | 987 | ret = gpio_request(phy->gpio_en, PN544_GPIO_NAME_EN); |
| 890 | if (ret) { | 988 | if (ret) { |
| 891 | nfc_err(&client->dev, "Fail EN pin\n"); | 989 | nfc_err(&client->dev, "Fail EN pin\n"); |
| 892 | goto err_dt; | 990 | goto err_dt; |
| @@ -908,7 +1006,7 @@ static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | |||
| 908 | phy->gpio_fw = ret; | 1006 | phy->gpio_fw = ret; |
| 909 | 1007 | ||
| 910 | /* Configuration of FW GPIO */ | 1008 | /* Configuration of FW GPIO */ |
| 911 | ret = gpio_request(phy->gpio_fw, "pn544_fw"); | 1009 | ret = gpio_request(phy->gpio_fw, PN544_GPIO_NAME_FW); |
| 912 | if (ret) { | 1010 | if (ret) { |
| 913 | nfc_err(&client->dev, "Fail FW pin\n"); | 1011 | nfc_err(&client->dev, "Fail FW pin\n"); |
| 914 | goto err_gpio_en; | 1012 | goto err_gpio_en; |
| @@ -1003,6 +1101,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
| 1003 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | 1101 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); |
| 1004 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | 1102 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); |
| 1005 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | 1103 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); |
| 1104 | /* Using ACPI */ | ||
| 1105 | } else if (ACPI_HANDLE(&client->dev)) { | ||
| 1106 | r = pn544_hci_i2c_acpi_request_resources(client); | ||
| 1107 | if (r) { | ||
| 1108 | nfc_err(&client->dev, | ||
| 1109 | "Cannot get ACPI data\n"); | ||
| 1110 | return r; | ||
| 1111 | } | ||
| 1006 | } else { | 1112 | } else { |
| 1007 | nfc_err(&client->dev, "No platform data\n"); | 1113 | nfc_err(&client->dev, "No platform data\n"); |
| 1008 | return -EINVAL; | 1114 | return -EINVAL; |
| @@ -1082,6 +1188,7 @@ static struct i2c_driver pn544_hci_i2c_driver = { | |||
| 1082 | .name = PN544_HCI_I2C_DRIVER_NAME, | 1188 | .name = PN544_HCI_I2C_DRIVER_NAME, |
| 1083 | .owner = THIS_MODULE, | 1189 | .owner = THIS_MODULE, |
| 1084 | .of_match_table = of_match_ptr(of_pn544_i2c_match), | 1190 | .of_match_table = of_match_ptr(of_pn544_i2c_match), |
| 1191 | .acpi_match_table = ACPI_PTR(pn544_hci_i2c_acpi_match), | ||
| 1085 | }, | 1192 | }, |
| 1086 | .probe = pn544_hci_i2c_probe, | 1193 | .probe = pn544_hci_i2c_probe, |
| 1087 | .id_table = pn544_hci_i2c_id_table, | 1194 | .id_table = pn544_hci_i2c_id_table, |
