aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/w1/w1.c40
-rw-r--r--drivers/w1/w1.h12
-rw-r--r--drivers/w1/w1_int.c16
-rw-r--r--drivers/w1/w1_io.c68
4 files changed, 131 insertions, 5 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 9b5c11701c37..32418d4e555a 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -246,10 +246,14 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
246 struct device_attribute *attr, 246 struct device_attribute *attr,
247 const char * buf, size_t count) 247 const char * buf, size_t count)
248{ 248{
249 long tmp;
249 struct w1_master *md = dev_to_w1_master(dev); 250 struct w1_master *md = dev_to_w1_master(dev);
250 251
252 if (strict_strtol(buf, 0, &tmp) == -EINVAL)
253 return -EINVAL;
254
251 mutex_lock(&md->mutex); 255 mutex_lock(&md->mutex);
252 md->search_count = simple_strtol(buf, NULL, 0); 256 md->search_count = tmp;
253 mutex_unlock(&md->mutex); 257 mutex_unlock(&md->mutex);
254 wake_up_process(md->thread); 258 wake_up_process(md->thread);
255 259
@@ -270,6 +274,38 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
270 return count; 274 return count;
271} 275}
272 276
277static ssize_t w1_master_attribute_store_pullup(struct device *dev,
278 struct device_attribute *attr,
279 const char *buf, size_t count)
280{
281 long tmp;
282 struct w1_master *md = dev_to_w1_master(dev);
283
284 if (strict_strtol(buf, 0, &tmp) == -EINVAL)
285 return -EINVAL;
286
287 mutex_lock(&md->mutex);
288 md->enable_pullup = tmp;
289 mutex_unlock(&md->mutex);
290 wake_up_process(md->thread);
291
292 return count;
293}
294
295static ssize_t w1_master_attribute_show_pullup(struct device *dev,
296 struct device_attribute *attr,
297 char *buf)
298{
299 struct w1_master *md = dev_to_w1_master(dev);
300 ssize_t count;
301
302 mutex_lock(&md->mutex);
303 count = sprintf(buf, "%d\n", md->enable_pullup);
304 mutex_unlock(&md->mutex);
305
306 return count;
307}
308
273static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf) 309static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
274{ 310{
275 struct w1_master *md = dev_to_w1_master(dev); 311 struct w1_master *md = dev_to_w1_master(dev);
@@ -365,6 +401,7 @@ static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
365static W1_MASTER_ATTR_RO(timeout, S_IRUGO); 401static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
366static W1_MASTER_ATTR_RO(pointer, S_IRUGO); 402static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
367static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); 403static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
404static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUGO);
368 405
369static struct attribute *w1_master_default_attrs[] = { 406static struct attribute *w1_master_default_attrs[] = {
370 &w1_master_attribute_name.attr, 407 &w1_master_attribute_name.attr,
@@ -375,6 +412,7 @@ static struct attribute *w1_master_default_attrs[] = {
375 &w1_master_attribute_timeout.attr, 412 &w1_master_attribute_timeout.attr,
376 &w1_master_attribute_pointer.attr, 413 &w1_master_attribute_pointer.attr,
377 &w1_master_attribute_search.attr, 414 &w1_master_attribute_search.attr,
415 &w1_master_attribute_pullup.attr,
378 NULL 416 NULL
379}; 417};
380 418
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 34ee01e008ad..00b84ab22808 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -142,6 +142,12 @@ struct w1_bus_master
142 */ 142 */
143 u8 (*reset_bus)(void *); 143 u8 (*reset_bus)(void *);
144 144
145 /**
146 * Put out a strong pull-up pulse of the specified duration.
147 * @return -1=Error, 0=completed
148 */
149 u8 (*set_pullup)(void *, int);
150
145 /** Really nice hardware can handles the different types of ROM search 151 /** Really nice hardware can handles the different types of ROM search
146 * w1_master* is passed to the slave found callback. 152 * w1_master* is passed to the slave found callback.
147 */ 153 */
@@ -167,6 +173,11 @@ struct w1_master
167 void *priv; 173 void *priv;
168 int priv_size; 174 int priv_size;
169 175
176 /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */
177 int enable_pullup;
178 /** 5V strong pullup duration in milliseconds, zero disabled. */
179 int pullup_duration;
180
170 struct task_struct *thread; 181 struct task_struct *thread;
171 struct mutex mutex; 182 struct mutex mutex;
172 183
@@ -201,6 +212,7 @@ u8 w1_calc_crc8(u8 *, int);
201void w1_write_block(struct w1_master *, const u8 *, int); 212void w1_write_block(struct w1_master *, const u8 *, int);
202u8 w1_read_block(struct w1_master *, u8 *, int); 213u8 w1_read_block(struct w1_master *, u8 *, int);
203int w1_reset_select_slave(struct w1_slave *sl); 214int w1_reset_select_slave(struct w1_slave *sl);
215void w1_next_pullup(struct w1_master *, int);
204 216
205static inline struct w1_slave* dev_to_w1_slave(struct device *dev) 217static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
206{ 218{
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index bd877b24ce42..9d723efdf915 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -31,6 +31,9 @@
31 31
32static u32 w1_ids = 1; 32static u32 w1_ids = 1;
33 33
34static int w1_enable_pullup = 1;
35module_param_named(enable_pullup, w1_enable_pullup, int, 0);
36
34static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, 37static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
35 struct device_driver *driver, 38 struct device_driver *driver,
36 struct device *device) 39 struct device *device)
@@ -59,6 +62,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
59 dev->initialized = 0; 62 dev->initialized = 0;
60 dev->id = id; 63 dev->id = id;
61 dev->slave_ttl = slave_ttl; 64 dev->slave_ttl = slave_ttl;
65 dev->enable_pullup = w1_enable_pullup;
62 dev->search_count = -1; /* continual scan */ 66 dev->search_count = -1; /* continual scan */
63 67
64 /* 1 for w1_process to decrement 68 /* 1 for w1_process to decrement
@@ -107,6 +111,18 @@ int w1_add_master_device(struct w1_bus_master *master)
107 printk(KERN_ERR "w1_add_master_device: invalid function set\n"); 111 printk(KERN_ERR "w1_add_master_device: invalid function set\n");
108 return(-EINVAL); 112 return(-EINVAL);
109 } 113 }
114 /* While it would be electrically possible to make a device that
115 * generated a strong pullup in bit bang mode, only hardare that
116 * controls 1-wire time frames are even expected to support a strong
117 * pullup. w1_io.c would need to support calling set_pullup before
118 * the last write_bit operation of a w1_write_8 which it currently
119 * doesn't.
120 */
121 if (!master->write_byte && !master->touch_bit && master->set_pullup) {
122 printk(KERN_ERR "w1_add_master_device: set_pullup requires "
123 "write_byte or touch_bit, disabling\n");
124 master->set_pullup = NULL;
125 }
110 126
111 dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device); 127 dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device);
112 if (!dev) 128 if (!dev)
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 0056ef69009b..97b338a16abc 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -93,6 +93,40 @@ static void w1_write_bit(struct w1_master *dev, int bit)
93} 93}
94 94
95/** 95/**
96 * Pre-write operation, currently only supporting strong pullups.
97 * Program the hardware for a strong pullup, if one has been requested and
98 * the hardware supports it.
99 *
100 * @param dev the master device
101 */
102static void w1_pre_write(struct w1_master *dev)
103{
104 if (dev->pullup_duration &&
105 dev->enable_pullup && dev->bus_master->set_pullup) {
106 dev->bus_master->set_pullup(dev->bus_master->data,
107 dev->pullup_duration);
108 }
109}
110
111/**
112 * Post-write operation, currently only supporting strong pullups.
113 * If a strong pullup was requested, clear it if the hardware supports
114 * them, or execute the delay otherwise, in either case clear the request.
115 *
116 * @param dev the master device
117 */
118static void w1_post_write(struct w1_master *dev)
119{
120 if (dev->pullup_duration) {
121 if (dev->enable_pullup && dev->bus_master->set_pullup)
122 dev->bus_master->set_pullup(dev->bus_master->data, 0);
123 else
124 msleep(dev->pullup_duration);
125 dev->pullup_duration = 0;
126 }
127}
128
129/**
96 * Writes 8 bits. 130 * Writes 8 bits.
97 * 131 *
98 * @param dev the master device 132 * @param dev the master device
@@ -102,11 +136,17 @@ void w1_write_8(struct w1_master *dev, u8 byte)
102{ 136{
103 int i; 137 int i;
104 138
105 if (dev->bus_master->write_byte) 139 if (dev->bus_master->write_byte) {
140 w1_pre_write(dev);
106 dev->bus_master->write_byte(dev->bus_master->data, byte); 141 dev->bus_master->write_byte(dev->bus_master->data, byte);
142 }
107 else 143 else
108 for (i = 0; i < 8; ++i) 144 for (i = 0; i < 8; ++i) {
145 if (i == 7)
146 w1_pre_write(dev);
109 w1_touch_bit(dev, (byte >> i) & 0x1); 147 w1_touch_bit(dev, (byte >> i) & 0x1);
148 }
149 w1_post_write(dev);
110} 150}
111EXPORT_SYMBOL_GPL(w1_write_8); 151EXPORT_SYMBOL_GPL(w1_write_8);
112 152
@@ -203,11 +243,14 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
203{ 243{
204 int i; 244 int i;
205 245
206 if (dev->bus_master->write_block) 246 if (dev->bus_master->write_block) {
247 w1_pre_write(dev);
207 dev->bus_master->write_block(dev->bus_master->data, buf, len); 248 dev->bus_master->write_block(dev->bus_master->data, buf, len);
249 }
208 else 250 else
209 for (i = 0; i < len; ++i) 251 for (i = 0; i < len; ++i)
210 w1_write_8(dev, buf[i]); 252 w1_write_8(dev, buf[i]); /* calls w1_pre_write */
253 w1_post_write(dev);
211} 254}
212EXPORT_SYMBOL_GPL(w1_write_block); 255EXPORT_SYMBOL_GPL(w1_write_block);
213 256
@@ -306,3 +349,20 @@ int w1_reset_select_slave(struct w1_slave *sl)
306 return 0; 349 return 0;
307} 350}
308EXPORT_SYMBOL_GPL(w1_reset_select_slave); 351EXPORT_SYMBOL_GPL(w1_reset_select_slave);
352
353/**
354 * Put out a strong pull-up of the specified duration after the next write
355 * operation. Not all hardware supports strong pullups. Hardware that
356 * doesn't support strong pullups will sleep for the given time after the
357 * write operation without a strong pullup. This is a one shot request for
358 * the next write, specifying zero will clear a previous request.
359 * The w1 master lock must be held.
360 *
361 * @param delay time in milliseconds
362 * @return 0=success, anything else=error
363 */
364void w1_next_pullup(struct w1_master *dev, int delay)
365{
366 dev->pullup_duration = delay;
367}
368EXPORT_SYMBOL_GPL(w1_next_pullup);