* [PATCH v3 1/2] NFC: pn544_i2c: Add device-tree (Open Firmware) support to PN544
@ 2014-03-31 12:21 Clement Perrochaud
[not found] ` <92d1a06e7bda4a46a0b6a28ba6ede55b-fjMGVQzTDdguRZvghep3ngfhPeD8jYilXA4E9RH9d+qIuWR1G4zioA@public.gmane.org>
0 siblings, 1 reply; 2+ messages in thread
From: Clement Perrochaud @ 2014-03-31 12:21 UTC (permalink / raw)
To: Clement Perrochaud,
linux-nfc-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
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-3arQi8VN3Tc@public.gmane.org>
---
drivers/nfc/pn544/i2c.c | 162 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 145 insertions(+), 17 deletions(-)
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index f2acd85..942abea 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -22,6 +22,8 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -857,6 +859,108 @@ exit_state_wait_secure_write_answer:
}
}
+#ifdef CONFIG_OF
+
+static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
+{
+ struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
+ struct device_node *pp;
+ int gpio[3];
+ int irq;
+ int ret;
+ int i;
+
+ pp = client->dev.of_node;
+ if (!pp) {
+ ret = -ENODEV;
+ goto err_dt;
+ }
+
+ /* Get GPIO from device tree */
+ gpio[NFC_GPIO_ENABLE] = of_get_named_gpio(pp, "en", 0);
+ gpio[NFC_GPIO_FW_RESET] = of_get_named_gpio(pp, "fw", 0);
+ gpio[NFC_GPIO_IRQ] = of_get_named_gpio(pp, "irq", 0);
+ for (i = 0; i < 3; i++) {
+ if (gpio[i] < 0) {
+ ret = gpio[i];
+ if (ret != -EPROBE_DEFER)
+ nfc_err(&client->dev, "Failed to get gpio %d, error: %d\n", i, ret);
+ goto err_dt;
+ }
+ }
+
+ /* GPIO request and configuration */
+ ret = gpio_request(gpio[NFC_GPIO_FW_RESET], "pn544_fw");
+ if (ret) {
+ nfc_err(&client->dev, "Fail FW pin\n");
+ goto err_dt;
+ }
+ ret = gpio_direction_output(gpio[NFC_GPIO_FW_RESET], 0);
+ if (ret) {
+ nfc_err(&client->dev, "Fail FW pin direction\n");
+ goto err_gpio_en;
+ }
+
+ ret = gpio_request(gpio[NFC_GPIO_ENABLE], "pn544_en");
+ if (ret) {
+ nfc_err(&client->dev, "Fail EN pin\n");
+ goto err_gpio_en;
+ }
+ ret = gpio_direction_output(gpio[NFC_GPIO_ENABLE], 0);
+ if (ret) {
+ nfc_err(&client->dev, "Fail EN pin direction\n");
+ goto err_gpio_irq;
+ }
+
+ ret = gpio_request(gpio[NFC_GPIO_IRQ], "pn544_irq");
+ if (ret) {
+ nfc_err(&client->dev, "Fail IRQ pin\n");
+ goto err_gpio_irq;
+ }
+ ret = gpio_direction_input(gpio[NFC_GPIO_IRQ]);
+ if (ret) {
+ nfc_err(&client->dev, "Fail IRQ pin direction\n");
+ goto err_irq;
+ }
+
+ /* GPIO assignation */
+ phy->gpio_en = gpio[NFC_GPIO_ENABLE];
+ phy->gpio_fw = gpio[NFC_GPIO_FW_RESET];
+ phy->gpio_irq = gpio[NFC_GPIO_IRQ];
+
+ /* IRQ */
+ irq = gpio_to_irq(gpio[NFC_GPIO_IRQ]);
+ if (irq < 0) {
+ ret = irq;
+ nfc_err(&client->dev,
+ "Unable to get irq number for GPIO %d, error %d\n",
+ gpio[NFC_GPIO_IRQ],
+ ret);
+ goto err_irq;
+ }
+ client->irq = irq;
+
+ return 0;
+
+err_irq:
+ gpio_free(gpio[NFC_GPIO_IRQ]);
+err_gpio_irq:
+ gpio_free(gpio[NFC_GPIO_ENABLE]);
+err_gpio_en:
+ gpio_free(gpio[NFC_GPIO_FW_RESET]);
+err_dt:
+ return ret;
+}
+
+#else
+
+static int pn544_hci_i2c_of_request_resources(struct i2c_client *client)
+{
+ return -ENODEV;
+}
+
+#endif
+
static int pn544_hci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -887,25 +991,32 @@ static int pn544_hci_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data;
- if (pdata == NULL) {
- nfc_err(&client->dev, "No platform data\n");
- return -EINVAL;
- }
- if (pdata->request_resources == NULL) {
- nfc_err(&client->dev, "request_resources() missing\n");
- return -EINVAL;
- }
+ /* No platform data, using device tree. */
+ if (!pdata && client->dev.of_node) {
+ r = pn544_hci_i2c_of_request_resources(client);
+ if (r) {
+ nfc_err(&client->dev, "No DT data\n");
+ return r;
+ }
+ /* Using platform data. */
+ } else {
- r = pdata->request_resources(client);
- if (r) {
- nfc_err(&client->dev, "Cannot get platform resources\n");
- return r;
- }
+ if (pdata->request_resources == NULL) {
+ nfc_err(&client->dev, "request_resources() missing\n");
+ return -EINVAL;
+ }
+
+ r = pdata->request_resources(client);
+ if (r) {
+ nfc_err(&client->dev, "Cannot get platform resources\n");
+ return r;
+ }
- phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
- phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
- phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
+ phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
+ phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
+ phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
+ }
pn544_hci_i2c_platform_init(phy);
@@ -953,15 +1064,32 @@ static int pn544_hci_i2c_remove(struct i2c_client *client)
pn544_hci_i2c_disable(phy);
free_irq(client->irq, phy);
- if (pdata->free_resources)
+
+ /* No platform data, GPIOs have been requested by this driver */
+ if (!pdata) {
+ gpio_free(phy->gpio_en);
+ gpio_free(phy->gpio_fw);
+ gpio_free(phy->gpio_irq);
+
+ /* Using platform data */
+ } else if (pdata->free_resources) {
pdata->free_resources();
+ }
return 0;
}
+static const struct of_device_id of_pn544_i2c_match[] = {
+ { .compatible = "nxp,pn544_i2c", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_pn544_i2c_match);
+
static struct i2c_driver pn544_hci_i2c_driver = {
.driver = {
.name = PN544_HCI_I2C_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_pn544_i2c_match),
},
.probe = pn544_hci_i2c_probe,
.id_table = pn544_hci_i2c_id_table,
--
1.9.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [linux-nfc] [PATCH v3 1/2] NFC: pn544_i2c: Add device-tree (Open Firmware) support to PN544
[not found] ` <92d1a06e7bda4a46a0b6a28ba6ede55b-fjMGVQzTDdguRZvghep3ngfhPeD8jYilXA4E9RH9d+qIuWR1G4zioA@public.gmane.org>
@ 2014-03-31 23:48 ` Samuel Ortiz
0 siblings, 0 replies; 2+ messages in thread
From: Samuel Ortiz @ 2014-03-31 23:48 UTC (permalink / raw)
To: Clement Perrochaud
Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Hi Clement,
One more comment:
On Mon, Mar 31, 2014 at 12:21:44PM +0000, Clement Perrochaud wrote:
> + /* No platform data, using device tree. */
> + if (!pdata && client->dev.of_node) {
> + r = pn544_hci_i2c_of_request_resources(client);
> + if (r) {
> + nfc_err(&client->dev, "No DT data\n");
> + return r;
> + }
> + /* Using platform data. */
> + } else {
That should be: } else if (pdata) {
as you need to check for pdata before dereferencing it.
And your final else will handle the error case where both pdata and of_node
are NULL.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-03-31 23:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-31 12:21 [PATCH v3 1/2] NFC: pn544_i2c: Add device-tree (Open Firmware) support to PN544 Clement Perrochaud
[not found] ` <92d1a06e7bda4a46a0b6a28ba6ede55b-fjMGVQzTDdguRZvghep3ngfhPeD8jYilXA4E9RH9d+qIuWR1G4zioA@public.gmane.org>
2014-03-31 23:48 ` [linux-nfc] " Samuel Ortiz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).