1/* 2 * Custom GPIO-based W1 driver 3 * 4 * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org> 5 * Copyright (C) 2008 Bifferos <bifferos at yahoo.co.uk> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * --------------------------------------------------------------------------- 12 * 13 * The behaviour of this driver can be altered by setting some parameters 14 * from the insmod command line. 15 * 16 * The following parameters are adjustable: 17 * 18 * bus0 These four arguments must be arrays of 19 * bus1 3 unsigned integers as follows: 20 * bus2 21 * bus3 <id>,<pin>,<od> 22 * 23 * where: 24 * 25 * <id> ID to used as device_id for the corresponding bus (required) 26 * <sda> GPIO pin ID of data pin (required) 27 * <od> Pin is configured as open drain. 28 * 29 * See include/w1-gpio.h for more information about the parameters. 30 * 31 * If this driver is built into the kernel, you can use the following kernel 32 * command line parameters, with the same values as the corresponding module 33 * parameters listed above: 34 * 35 * w1-gpio-custom.bus0 36 * w1-gpio-custom.bus1 37 * w1-gpio-custom.bus2 38 * w1-gpio-custom.bus3 39 */ 40 41#include <linux/kernel.h> 42#include <linux/module.h> 43#include <linux/init.h> 44#include <linux/platform_device.h> 45 46#include <linux/w1-gpio.h> 47 48#define DRV_NAME "w1-gpio-custom" 49#define DRV_DESC "Custom GPIO-based W1 driver" 50#define DRV_VERSION "0.1.1" 51 52#define PFX DRV_NAME ": " 53 54#define BUS_PARAM_ID 0 55#define BUS_PARAM_PIN 1 56#define BUS_PARAM_OD 2 57 58#define BUS_PARAM_REQUIRED 3 59#define BUS_PARAM_COUNT 3 60#define BUS_COUNT_MAX 4 61 62static unsigned int bus0[BUS_PARAM_COUNT] __initdata; 63static unsigned int bus1[BUS_PARAM_COUNT] __initdata; 64static unsigned int bus2[BUS_PARAM_COUNT] __initdata; 65static unsigned int bus3[BUS_PARAM_COUNT] __initdata; 66 67static unsigned int bus_nump[BUS_COUNT_MAX] __initdata; 68 69#define BUS_PARM_DESC " config -> id,pin,od" 70 71module_param_array(bus0, uint, &bus_nump[0], 0); 72MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC); 73module_param_array(bus1, uint, &bus_nump[1], 0); 74MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC); 75module_param_array(bus2, uint, &bus_nump[2], 0); 76MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC); 77module_param_array(bus3, uint, &bus_nump[3], 0); 78MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC); 79 80static struct platform_device *devices[BUS_COUNT_MAX]; 81static unsigned int nr_devices; 82 83static void w1_gpio_custom_cleanup(void) 84{ 85 int i; 86 87 for (i = 0; i < nr_devices; i++) 88 if (devices[i]) 89 platform_device_put(devices[i]); 90} 91 92static int __init w1_gpio_custom_add_one(unsigned int id, unsigned int *params) 93{ 94 struct platform_device *pdev; 95 struct w1_gpio_platform_data pdata; 96 int err; 97 98 if (!bus_nump[id]) 99 return 0; 100 101 if (bus_nump[id] < BUS_PARAM_REQUIRED) { 102 printk(KERN_ERR PFX "not enough parameters for bus%d\n", id); 103 err = -EINVAL; 104 goto err; 105 } 106 107 pdev = platform_device_alloc("w1-gpio", params[BUS_PARAM_ID]); 108 if (!pdev) { 109 err = -ENOMEM; 110 goto err; 111 } 112 113 pdata.pin = params[BUS_PARAM_PIN]; 114 pdata.is_open_drain = params[BUS_PARAM_OD] ? 1 : 0; 115 pdata.enable_external_pullup = NULL; 116 pdata.ext_pullup_enable_pin = -EINVAL; 117 118 err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 119 if (err) 120 goto err_put; 121 122 err = platform_device_add(pdev); 123 if (err) 124 goto err_put; 125 126 devices[nr_devices++] = pdev; 127 return 0; 128 129 err_put: 130 platform_device_put(pdev); 131 err: 132 return err; 133} 134 135static int __init w1_gpio_custom_probe(void) 136{ 137 int err; 138 139 nr_devices = 0; 140 printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); 141 142 err = w1_gpio_custom_add_one(0, bus0); 143 if (err) 144 goto err; 145 146 err = w1_gpio_custom_add_one(1, bus1); 147 if (err) 148 goto err; 149 150 err = w1_gpio_custom_add_one(2, bus2); 151 if (err) 152 goto err; 153 154 err = w1_gpio_custom_add_one(3, bus3); 155 if (err) 156 goto err; 157 158 if (!nr_devices) { 159 printk(KERN_ERR PFX "no bus parameter(s) specified\n"); 160 err = -ENODEV; 161 goto err; 162 } 163 164 return 0; 165 166err: 167 w1_gpio_custom_cleanup(); 168 return err; 169} 170 171#ifdef MODULE 172static int __init w1_gpio_custom_init(void) 173{ 174 return w1_gpio_custom_probe(); 175} 176module_init(w1_gpio_custom_init); 177 178static void __exit w1_gpio_custom_exit(void) 179{ 180 w1_gpio_custom_cleanup(); 181} 182module_exit(w1_gpio_custom_exit); 183#else 184subsys_initcall(w1_gpio_custom_probe); 185#endif /* MODULE*/ 186 187MODULE_LICENSE("GPL v2"); 188MODULE_AUTHOR("Bifferos <bifferos at yahoo.co.uk >"); 189MODULE_DESCRIPTION(DRV_DESC); 190MODULE_VERSION(DRV_VERSION); 191