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 /drivers/nfc | |
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>
Diffstat (limited to 'drivers/nfc')
-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, |