summaryrefslogtreecommitdiff
path: root/drivers/w1/masters/w1-gpio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 23:09:59 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 23:09:59 +0400
commit3aebd34b1200a902a8662da8845824a02f00772e (patch)
tree13eac224dc1ac40be53bccc90f27bebf2e619c26 /drivers/w1/masters/w1-gpio.c
parent2c0c86d5b67ee04e8b71a2ea2a3af6d224611cfc (diff)
parent5dc2db05f2f690d71d95979b14cca50ab8e49f40 (diff)
downloadlinux-3aebd34b1200a902a8662da8845824a02f00772e.tar.xz
Merge tag 'char-misc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver merge from Greg Kroah-Hartman: "Here is the "big" char/misc driver tree update for the 3.7-rc1 merge window. Nothing major, just a number of driver updates and fixes, all of which have been in the linux-next releases for a while now either in my tree, or in Andrew's (the lis3l driver changes came from his tree last week). Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" * tag 'char-misc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (52 commits) drivers/misc/lis3lv02d/lis3lv02d_i2c.c: add lis3lv02d device tree init drivers/misc/lis3lv02d/lis3lv02d_spi.c: add lis3lv02d device tree init drivers/misc/lis3lv02d: remove lis3lv02d driver DT init drivers/misc/lis3lv02d/lis3lv02d_spi.c: add DT matching table passthru code drivers/misc/lis3lv02d: add generic DT matching code lis3lv02d: fix some comments specific to lis331dlh driver MISC: hpilo, remove pci_disable_device pcmcia: synclink_cs: fix potential tty NULL dereference drivers/char/mmtimer.c: Remove useless kfree drivers/char: removes unnecessary semicolon char/misc: remove CONFIG_EXPERIMENTAL dependencies mei: don't print buffer as a string mei: struct mei_message_data doesn't have to be packed mei: add error messages for open count errors misc: use module_spi_driver tifm: use module_pci_driver misc/at25, dt: Improve at25 SPI eeprom device tree bindings. mei: add lynx point pci device ids mei: fix max number of open handles mei: rename struct pci_dev *mei_device to mei_pdev ...
Diffstat (limited to 'drivers/w1/masters/w1-gpio.c')
-rw-r--r--drivers/w1/masters/w1-gpio.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index df600d14974d..6012c4ea3206 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -14,6 +14,8 @@
#include <linux/slab.h>
#include <linux/w1-gpio.h>
#include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
#include "../w1.h"
#include "../w1_int.h"
@@ -42,12 +44,55 @@ static u8 w1_gpio_read_bit(void *data)
return gpio_get_value(pdata->pin) ? 1 : 0;
}
+#ifdef CONFIG_OF
+static struct of_device_id w1_gpio_dt_ids[] = {
+ { .compatible = "w1-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
+
+static int w1_gpio_probe_dt(struct platform_device *pdev)
+{
+ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(w1_gpio_dt_ids, &pdev->dev);
+
+ if (!of_id)
+ return 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ if (of_get_property(np, "linux,open-drain", NULL))
+ pdata->is_open_drain = 1;
+
+ pdata->pin = of_get_gpio(np, 0);
+ pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
+ pdev->dev.platform_data = pdata;
+
+ return 0;
+}
+#else
+static int w1_gpio_probe_dt(struct platform_device *pdev)
+{
+ return 0;
+}
+#endif
+
static int __init w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct w1_gpio_platform_data *pdata;
int err;
+ err = w1_gpio_probe_dt(pdev);
+ if (err < 0)
+ return err;
+
+ pdata = pdev->dev.platform_data;
+
if (!pdata)
return -ENXIO;
@@ -59,6 +104,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
if (err)
goto free_master;
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
+ err = gpio_request_one(pdata->ext_pullup_enable_pin,
+ GPIOF_INIT_LOW, "w1 pullup");
+ if (err < 0)
+ goto free_gpio;
+ }
+
master->data = pdata;
master->read_bit = w1_gpio_read_bit;
@@ -72,15 +124,21 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
err = w1_add_master_device(master);
if (err)
- goto free_gpio;
+ goto free_gpio_ext_pu;
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1);
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin))
+ gpio_set_value(pdata->ext_pullup_enable_pin, 1);
+
platform_set_drvdata(pdev, master);
return 0;
+ free_gpio_ext_pu:
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin))
+ gpio_free(pdata->ext_pullup_enable_pin);
free_gpio:
gpio_free(pdata->pin);
free_master:
@@ -97,6 +155,9 @@ static int __exit w1_gpio_remove(struct platform_device *pdev)
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0);
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin))
+ gpio_set_value(pdata->ext_pullup_enable_pin, 0);
+
w1_remove_master_device(master);
gpio_free(pdata->pin);
kfree(master);
@@ -135,6 +196,7 @@ static struct platform_driver w1_gpio_driver = {
.driver = {
.name = "w1-gpio",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(w1_gpio_dt_ids),
},
.remove = __exit_p(w1_gpio_remove),
.suspend = w1_gpio_suspend,