| 
									
										
										
										
											2008-02-06 01:39:01 -08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-12 14:31:25 -07:00
										 |  |  | 	return gpio_get_value(pdata->pin) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2008-02-06 01:39:01 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-17 16:28:15 -07:00
										 |  |  | 	if (pdata->enable_external_pullup) | 
					
						
							|  |  |  | 		pdata->enable_external_pullup(1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 01:39:01 -08:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-17 16:28:15 -07:00
										 |  |  | 	if (pdata->enable_external_pullup) | 
					
						
							|  |  |  | 		pdata->enable_external_pullup(0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 01:39:01 -08:00
										 |  |  | 	w1_remove_master_device(master); | 
					
						
							|  |  |  | 	gpio_free(pdata->pin); | 
					
						
							|  |  |  | 	kfree(master); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-17 16:28:15 -07:00
										 |  |  | #ifdef CONFIG_PM
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pdata->enable_external_pullup) | 
					
						
							|  |  |  | 		pdata->enable_external_pullup(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int w1_gpio_resume(struct platform_device *pdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pdata->enable_external_pullup) | 
					
						
							|  |  |  | 		pdata->enable_external_pullup(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define w1_gpio_suspend	NULL
 | 
					
						
							|  |  |  | #define w1_gpio_resume	NULL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 01:39:01 -08:00
										 |  |  | static struct platform_driver w1_gpio_driver = { | 
					
						
							|  |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name	= "w1-gpio", | 
					
						
							|  |  |  | 		.owner	= THIS_MODULE, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	.remove	= __exit_p(w1_gpio_remove), | 
					
						
							| 
									
										
										
										
											2009-06-17 16:28:15 -07:00
										 |  |  | 	.suspend = w1_gpio_suspend, | 
					
						
							|  |  |  | 	.resume = w1_gpio_resume, | 
					
						
							| 
									
										
										
										
											2008-02-06 01:39:01 -08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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"); |