diff options
Diffstat (limited to 'drivers/w1/masters/w1-gpio.c')
-rw-r--r-- | drivers/w1/masters/w1-gpio.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000000000000..9e1138a75e8b --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,124 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/w1-gpio.h> + +#include "../w1.h" +#include "../w1_int.h" + +#include <asm/gpio.h> + +static void w1_gpio_write_bit_dir(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + if (bit) + gpio_direction_input(pdata->pin); + else + gpio_direction_output(pdata->pin, 0); +} + +static void w1_gpio_write_bit_val(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->pin); +} + +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; + int err; + + if (!pdata) + return -ENXIO; + + master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL); + if (!master) + return -ENOMEM; + + err = gpio_request(pdata->pin, "w1"); + if (err) + goto free_master; + + master->data = pdata; + master->read_bit = w1_gpio_read_bit; + + if (pdata->is_open_drain) { + gpio_direction_output(pdata->pin, 1); + master->write_bit = w1_gpio_write_bit_val; + } else { + gpio_direction_input(pdata->pin); + master->write_bit = w1_gpio_write_bit_dir; + } + + err = w1_add_master_device(master); + if (err) + goto free_gpio; + + platform_set_drvdata(pdev, master); + + return 0; + + free_gpio: + gpio_free(pdata->pin); + free_master: + kfree(master); + + return err; +} + +static int __exit w1_gpio_remove(struct platform_device *pdev) +{ + struct w1_bus_master *master = platform_get_drvdata(pdev); + struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; + + w1_remove_master_device(master); + gpio_free(pdata->pin); + kfree(master); + + return 0; +} + +static struct platform_driver w1_gpio_driver = { + .driver = { + .name = "w1-gpio", + .owner = THIS_MODULE, + }, + .remove = __exit_p(w1_gpio_remove), +}; + +static int __init w1_gpio_init(void) +{ + return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe); +} + +static void __exit w1_gpio_exit(void) +{ + platform_driver_unregister(&w1_gpio_driver); +} + +module_init(w1_gpio_init); +module_exit(w1_gpio_exit); + +MODULE_DESCRIPTION("GPIO w1 bus master driver"); +MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); +MODULE_LICENSE("GPL"); |