1/* 2 * w1-gpio - GPIO w1 bus master driver 3 * 4 * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation. 9 */ 10 11#include <linux/init.h> 12#include <linux/module.h> 13#include <linux/platform_device.h> 14#include <linux/slab.h> 15#include <linux/w1-gpio.h> 16 17#include "../w1.h" 18#include "../w1_int.h" 19 20#include <asm/gpio.h> 21 22static void w1_gpio_write_bit_dir(void *data, u8 bit) 23{ 24 struct w1_gpio_platform_data *pdata = data; 25 26 if (bit) 27 gpio_direction_input(pdata->pin); 28 else 29 gpio_direction_output(pdata->pin, 0); 30} 31 32static void w1_gpio_write_bit_val(void *data, u8 bit) 33{ 34 struct w1_gpio_platform_data *pdata = data; 35 36 gpio_set_value(pdata->pin, bit); 37} 38 39static u8 w1_gpio_read_bit(void *data) 40{ 41 struct w1_gpio_platform_data *pdata = data; 42 43 return gpio_get_value(pdata->pin) ? 1 : 0; 44} 45 46static int __init w1_gpio_probe(struct platform_device *pdev) 47{ 48 struct w1_bus_master *master; 49 struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; 50 int err; 51 52 if (!pdata) 53 return -ENXIO; 54 55 master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL); 56 if (!master) 57 return -ENOMEM; 58 59 err = gpio_request(pdata->pin, "w1"); 60 if (err) 61 goto free_master; 62 63 master->data = pdata; 64 master->read_bit = w1_gpio_read_bit; 65 66 if (pdata->is_open_drain) { 67 gpio_direction_output(pdata->pin, 1); 68 master->write_bit = w1_gpio_write_bit_val; 69 } else { 70 gpio_direction_input(pdata->pin); 71 master->write_bit = w1_gpio_write_bit_dir; 72 } 73 74 err = w1_add_master_device(master); 75 if (err) 76 goto free_gpio; 77 78 if (pdata->enable_external_pullup) 79 pdata->enable_external_pullup(1); 80 81 platform_set_drvdata(pdev, master); 82 83 return 0; 84 85 free_gpio: 86 gpio_free(pdata->pin); 87 free_master: 88 kfree(master); 89 90 return err; 91} 92 93static int __exit w1_gpio_remove(struct platform_device *pdev) 94{ 95 struct w1_bus_master *master = platform_get_drvdata(pdev); 96 struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; 97 98 if (pdata->enable_external_pullup) 99 pdata->enable_external_pullup(0); 100 101 w1_remove_master_device(master); 102 gpio_free(pdata->pin); 103 kfree(master); 104 105 return 0; 106} 107 108#ifdef CONFIG_PM 109 110static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state) 111{ 112 struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; 113 114 if (pdata->enable_external_pullup) 115 pdata->enable_external_pullup(0); 116 117 return 0; 118} 119 120static int w1_gpio_resume(struct platform_device *pdev) 121{ 122 struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; 123 124 if (pdata->enable_external_pullup) 125 pdata->enable_external_pullup(1); 126 127 return 0; 128} 129 130#else 131#define w1_gpio_suspend NULL 132#define w1_gpio_resume NULL 133#endif 134 135static struct platform_driver w1_gpio_driver = { 136 .driver = { 137 .name = "w1-gpio", 138 .owner = THIS_MODULE, 139 }, 140 .remove = __exit_p(w1_gpio_remove), 141 .suspend = w1_gpio_suspend, 142 .resume = w1_gpio_resume, 143}; 144 145static int __init w1_gpio_init(void) 146{ 147 return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe); 148} 149 150static void __exit w1_gpio_exit(void) 151{ 152 platform_driver_unregister(&w1_gpio_driver); 153} 154 155module_init(w1_gpio_init); 156module_exit(w1_gpio_exit); 157 158MODULE_DESCRIPTION("GPIO w1 bus master driver"); 159MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); 160MODULE_LICENSE("GPL"); 161