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