aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Perrochaud <clement.perrochaud@nxp.com>2014-04-02 05:02:39 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2014-04-21 18:37:26 -0400
commiteda8565af33648aa77cc2ea6c453b7cbaf53b1f1 (patch)
treeb733167b8b6f7fc6882585828125ab3c57af3dfb
parent58e1e0a920358cd0dd7fdccc8cbcaa1d117078cf (diff)
NFC: pn544: i2c: Add device-tree (Open Firmware) support to PN544
Add functions to recover hardware resources from the device-tree when not provided by the platform data. Signed-off-by: Clément Perrochaud <clement.perrochaud@nxp.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/nfc/pn544/i2c.c148
1 files changed, 131 insertions, 17 deletions
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index f2acd85be86e..5239e3b54120 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -22,6 +22,8 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/i2c.h> 23#include <linux/i2c.h>
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/of_gpio.h>
26#include <linux/of_irq.h>
25#include <linux/miscdevice.h> 27#include <linux/miscdevice.h>
26#include <linux/interrupt.h> 28#include <linux/interrupt.h>
27#include <linux/delay.h> 29#include <linux/delay.h>
@@ -857,6 +859,92 @@ exit_state_wait_secure_write_answer:
857 } 859 }
858} 860}
859 861
862#ifdef CONFIG_OF
863
864static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
865{
866 struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
867 struct device_node *pp;
868 int ret;
869
870 pp = client->dev.of_node;
871 if (!pp) {
872 ret = -ENODEV;
873 goto err_dt;
874 }
875
876 /* Obtention of EN GPIO from device tree */
877 ret = of_get_named_gpio(pp, "enable-gpios", 0);
878 if (ret < 0) {
879 if (ret != -EPROBE_DEFER)
880 nfc_err(&client->dev,
881 "Failed to get EN gpio, error: %d\n", ret);
882 goto err_dt;
883 }
884 phy->gpio_en = ret;
885
886 /* Configuration of EN GPIO */
887 ret = gpio_request(phy->gpio_en, "pn544_en");
888 if (ret) {
889 nfc_err(&client->dev, "Fail EN pin\n");
890 goto err_dt;
891 }
892 ret = gpio_direction_output(phy->gpio_en, 0);
893 if (ret) {
894 nfc_err(&client->dev, "Fail EN pin direction\n");
895 goto err_gpio_en;
896 }
897
898 /* Obtention of FW GPIO from device tree */
899 ret = of_get_named_gpio(pp, "firmware-gpios", 0);
900 if (ret < 0) {
901 if (ret != -EPROBE_DEFER)
902 nfc_err(&client->dev,
903 "Failed to get FW gpio, error: %d\n", ret);
904 goto err_gpio_en;
905 }
906 phy->gpio_fw = ret;
907
908 /* Configuration of FW GPIO */
909 ret = gpio_request(phy->gpio_fw, "pn544_fw");
910 if (ret) {
911 nfc_err(&client->dev, "Fail FW pin\n");
912 goto err_gpio_en;
913 }
914 ret = gpio_direction_output(phy->gpio_fw, 0);
915 if (ret) {
916 nfc_err(&client->dev, "Fail FW pin direction\n");
917 goto err_gpio_fw;
918 }
919
920 /* IRQ */
921 ret = irq_of_parse_and_map(pp, 0);
922 if (ret < 0) {
923 nfc_err(&client->dev,
924 "Unable to get irq, error: %d\n", ret);
925 goto err_gpio_fw;
926 }
927 client->irq = ret;
928
929 return 0;
930
931err_gpio_fw:
932 gpio_free(phy->gpio_fw);
933err_gpio_en:
934 gpio_free(phy->gpio_en);
935err_dt:
936 return ret;
937}
938
939#else
940
941static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
942{
943 return -ENODEV;
944}
945
946#endif
947
860static int pn544_hci_i2c_probe(struct i2c_client *client, 948static int pn544_hci_i2c_probe(struct i2c_client *client,
861 const struct i2c_device_id *id) 949 const struct i2c_device_id *id)
862{ 950{
@@ -887,25 +975,36 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
887 i2c_set_clientdata(client, phy); 975 i2c_set_clientdata(client, phy);
888 976
889 pdata = client->dev.platform_data; 977 pdata = client->dev.platform_data;
890 if (pdata == NULL) {
891 nfc_err(&client->dev, "No platform data\n");
892 return -EINVAL;
893 }
894 978
895 if (pdata->request_resources == NULL) { 979 /* No platform data, using device tree. */
896 nfc_err(&client->dev, "request_resources() missing\n"); 980 if (!pdata && client->dev.of_node) {
897 return -EINVAL; 981 r = pn544_hci_i2c_of_request_resources(client);
898 } 982 if (r) {
983 nfc_err(&client->dev, "No DT data\n");
984 return r;
985 }
986 /* Using platform data. */
987 } else if (pdata) {
899 988
900 r = pdata->request_resources(client); 989 if (pdata->request_resources == NULL) {
901 if (r) { 990 nfc_err(&client->dev, "request_resources() missing\n");
902 nfc_err(&client->dev, "Cannot get platform resources\n"); 991 return -EINVAL;
903 return r; 992 }
904 } 993
994 r = pdata->request_resources(client);
995 if (r) {
996 nfc_err(&client->dev,
997 "Cannot get platform resources\n");
998 return r;
999 }
905 1000
906 phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); 1001 phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
907 phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); 1002 phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
908 phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); 1003 phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
1004 } else {
1005 nfc_err(&client->dev, "No platform data\n");
1006 return -EINVAL;
1007 }
909 1008
910 pn544_hci_i2c_platform_init(phy); 1009 pn544_hci_i2c_platform_init(phy);
911 1010
@@ -953,15 +1052,30 @@ static int pn544_hci_i2c_remove(struct i2c_client *client)
953 pn544_hci_i2c_disable(phy); 1052 pn544_hci_i2c_disable(phy);
954 1053
955 free_irq(client->irq, phy); 1054 free_irq(client->irq, phy);
956 if (pdata->free_resources) 1055
1056 /* No platform data, GPIOs have been requested by this driver */
1057 if (!pdata) {
1058 gpio_free(phy->gpio_en);
1059 gpio_free(phy->gpio_fw);
1060 /* Using platform data */
1061 } else if (pdata->free_resources) {
957 pdata->free_resources(); 1062 pdata->free_resources();
1063 }
958 1064
959 return 0; 1065 return 0;
960} 1066}
961 1067
1068static const struct of_device_id of_pn544_i2c_match[] = {
1069 { .compatible = "nxp,pn544-i2c", },
1070 {},
1071};
1072MODULE_DEVICE_TABLE(of, of_pn544_i2c_match);
1073
962static struct i2c_driver pn544_hci_i2c_driver = { 1074static struct i2c_driver pn544_hci_i2c_driver = {
963 .driver = { 1075 .driver = {
964 .name = PN544_HCI_I2C_DRIVER_NAME, 1076 .name = PN544_HCI_I2C_DRIVER_NAME,
1077 .owner = THIS_MODULE,
1078 .of_match_table = of_match_ptr(of_pn544_i2c_match),
965 }, 1079 },
966 .probe = pn544_hci_i2c_probe, 1080 .probe = pn544_hci_i2c_probe,
967 .id_table = pn544_hci_i2c_id_table, 1081 .id_table = pn544_hci_i2c_id_table,