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 22 static 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 32 static 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 39 static 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 46 static 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 93 static 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 110 static 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 120 static 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 135 static 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 145 static int __init w1_gpio_init(void) 146 { 147 return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe); 148 } 149 150 static void __exit w1_gpio_exit(void) 151 { 152 platform_driver_unregister(&w1_gpio_driver); 153 } 154 155 module_init(w1_gpio_init); 156 module_exit(w1_gpio_exit); 157 158 MODULE_DESCRIPTION("GPIO w1 bus master driver"); 159 MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); 160 MODULE_LICENSE("GPL"); 161