diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 23:09:59 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 23:09:59 +0400 |
commit | 3aebd34b1200a902a8662da8845824a02f00772e (patch) | |
tree | 13eac224dc1ac40be53bccc90f27bebf2e619c26 /drivers/w1/masters/w1-gpio.c | |
parent | 2c0c86d5b67ee04e8b71a2ea2a3af6d224611cfc (diff) | |
parent | 5dc2db05f2f690d71d95979b14cca50ab8e49f40 (diff) | |
download | linux-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.c | 66 |
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, |