2 * w1_ds2408.c - w1 family 29 (DS2408) driver
4 * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
6 * This source code is licensed under the GNU General Public License,
7 * Version 2. See the file COPYING for more details.
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/device.h>
14 #include <linux/types.h>
15 #include <linux/delay.h>
16 #include <linux/slab.h>
19 #include "../w1_int.h"
20 #include "../w1_family.h"
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
24 MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
25 MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));
28 #define W1_F29_RETRIES 3
30 #define W1_F29_REG_LOGIG_STATE 0x88 /* R */
31 #define W1_F29_REG_OUTPUT_LATCH_STATE 0x89 /* R */
32 #define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A /* R */
33 #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
34 #define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C /* RW */
35 #define W1_F29_REG_CONTROL_AND_STATUS 0x8D /* RW */
37 #define W1_F29_FUNC_READ_PIO_REGS 0xF0
38 #define W1_F29_FUNC_CHANN_ACCESS_READ 0xF5
39 #define W1_F29_FUNC_CHANN_ACCESS_WRITE 0x5A
40 /* also used to write the control/status reg (0x8D): */
41 #define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC
42 #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
44 #define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA
46 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
50 "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
51 sl, (unsigned int)address, buf);
56 mutex_lock(&sl->master->bus_mutex);
57 dev_dbg(&sl->dev, "mutex locked");
59 if (w1_reset_select_slave(sl)) {
60 mutex_unlock(&sl->master->bus_mutex);
64 wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
67 w1_write_block(sl->master, wrbuf, 3);
68 *buf = w1_read_8(sl->master);
70 mutex_unlock(&sl->master->bus_mutex);
71 dev_dbg(&sl->dev, "mutex unlocked");
75 static ssize_t w1_f29_read_state(
76 struct file *filp, struct kobject *kobj,
77 struct bin_attribute *bin_attr,
78 char *buf, loff_t off, size_t count)
80 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
81 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
82 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
83 if (count != 1 || off != 0)
85 return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
88 static ssize_t w1_f29_read_output(
89 struct file *filp, struct kobject *kobj,
90 struct bin_attribute *bin_attr,
91 char *buf, loff_t off, size_t count)
93 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
94 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
95 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
96 if (count != 1 || off != 0)
98 return _read_reg(kobj_to_w1_slave(kobj),
99 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
102 static ssize_t w1_f29_read_activity(
103 struct file *filp, struct kobject *kobj,
104 struct bin_attribute *bin_attr,
105 char *buf, loff_t off, size_t count)
107 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
108 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
109 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
110 if (count != 1 || off != 0)
112 return _read_reg(kobj_to_w1_slave(kobj),
113 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
116 static ssize_t w1_f29_read_cond_search_mask(
117 struct file *filp, struct kobject *kobj,
118 struct bin_attribute *bin_attr,
119 char *buf, loff_t off, size_t count)
121 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
122 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
123 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
124 if (count != 1 || off != 0)
126 return _read_reg(kobj_to_w1_slave(kobj),
127 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
130 static ssize_t w1_f29_read_cond_search_polarity(
131 struct file *filp, struct kobject *kobj,
132 struct bin_attribute *bin_attr,
133 char *buf, loff_t off, size_t count)
135 if (count != 1 || off != 0)
137 return _read_reg(kobj_to_w1_slave(kobj),
138 W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
141 static ssize_t w1_f29_read_status_control(
142 struct file *filp, struct kobject *kobj,
143 struct bin_attribute *bin_attr,
144 char *buf, loff_t off, size_t count)
146 if (count != 1 || off != 0)
148 return _read_reg(kobj_to_w1_slave(kobj),
149 W1_F29_REG_CONTROL_AND_STATUS, buf);
155 static ssize_t w1_f29_write_output(
156 struct file *filp, struct kobject *kobj,
157 struct bin_attribute *bin_attr,
158 char *buf, loff_t off, size_t count)
160 struct w1_slave *sl = kobj_to_w1_slave(kobj);
163 unsigned int retries = W1_F29_RETRIES;
165 if (count != 1 || off != 0)
168 dev_dbg(&sl->dev, "locking mutex for write_output");
169 mutex_lock(&sl->master->bus_mutex);
170 dev_dbg(&sl->dev, "mutex locked");
172 if (w1_reset_select_slave(sl))
176 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
179 w1_write_block(sl->master, w1_buf, 3);
181 readBack = w1_read_8(sl->master);
183 if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
184 if (w1_reset_resume_command(sl->master))
186 /* try again, the slave is ready for a command */
190 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK
191 /* here the master could read another byte which
192 would be the PIO reg (the actual pin logic state)
193 since in this driver we don't know which pins are
194 in and outs, there's no value to read the state and
195 compare. with (*buf) so end this command abruptly: */
196 if (w1_reset_resume_command(sl->master))
199 /* go read back the output latches */
200 /* (the direct effect of the write above) */
201 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
202 w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
204 w1_write_block(sl->master, w1_buf, 3);
205 /* read the result of the READ_PIO_REGS command */
206 if (w1_read_8(sl->master) == *buf)
210 mutex_unlock(&sl->master->bus_mutex);
212 "mutex unlocked, retries:%d", retries);
217 mutex_unlock(&sl->master->bus_mutex);
218 dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
225 * Writing to the activity file resets the activity latches.
227 static ssize_t w1_f29_write_activity(
228 struct file *filp, struct kobject *kobj,
229 struct bin_attribute *bin_attr,
230 char *buf, loff_t off, size_t count)
232 struct w1_slave *sl = kobj_to_w1_slave(kobj);
233 unsigned int retries = W1_F29_RETRIES;
235 if (count != 1 || off != 0)
238 mutex_lock(&sl->master->bus_mutex);
240 if (w1_reset_select_slave(sl))
244 w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
245 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
246 mutex_unlock(&sl->master->bus_mutex);
249 if (w1_reset_resume_command(sl->master))
254 mutex_unlock(&sl->master->bus_mutex);
258 static ssize_t w1_f29_write_status_control(
260 struct kobject *kobj,
261 struct bin_attribute *bin_attr,
266 struct w1_slave *sl = kobj_to_w1_slave(kobj);
268 unsigned int retries = W1_F29_RETRIES;
270 if (count != 1 || off != 0)
273 mutex_lock(&sl->master->bus_mutex);
275 if (w1_reset_select_slave(sl))
279 w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
280 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
284 w1_write_block(sl->master, w1_buf, 4);
285 if (w1_reset_resume_command(sl->master))
288 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
289 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
292 w1_write_block(sl->master, w1_buf, 3);
293 if (w1_read_8(sl->master) == *buf) {
295 mutex_unlock(&sl->master->bus_mutex);
300 mutex_unlock(&sl->master->bus_mutex);
307 static struct bin_attribute w1_f29_sysfs_bin_files[] = {
314 .read = w1_f29_read_state,
319 .mode = S_IRUGO | S_IWUSR | S_IWGRP,
322 .read = w1_f29_read_output,
323 .write = w1_f29_write_output,
331 .read = w1_f29_read_activity,
332 .write = w1_f29_write_activity,
336 .name = "cond_search_mask",
340 .read = w1_f29_read_cond_search_mask,
344 .name = "cond_search_polarity",
348 .read = w1_f29_read_cond_search_polarity,
352 .name = "status_control",
353 .mode = S_IRUGO | S_IWUSR | S_IWGRP,
356 .read = w1_f29_read_status_control,
357 .write = w1_f29_write_status_control,
361 static int w1_f29_add_slave(struct w1_slave *sl)
366 for (i = 0; i < ARRAY_SIZE(w1_f29_sysfs_bin_files) && !err; ++i)
367 err = sysfs_create_bin_file(
369 &(w1_f29_sysfs_bin_files[i]));
372 sysfs_remove_bin_file(&sl->dev.kobj,
373 &(w1_f29_sysfs_bin_files[i]));
377 static void w1_f29_remove_slave(struct w1_slave *sl)
380 for (i = ARRAY_SIZE(w1_f29_sysfs_bin_files) - 1; i >= 0; --i)
381 sysfs_remove_bin_file(&sl->dev.kobj,
382 &(w1_f29_sysfs_bin_files[i]));
385 static struct w1_family_ops w1_f29_fops = {
386 .add_slave = w1_f29_add_slave,
387 .remove_slave = w1_f29_remove_slave,
390 static struct w1_family w1_family_29 = {
391 .fid = W1_FAMILY_DS2408,
392 .fops = &w1_f29_fops,
395 static int __init w1_f29_init(void)
397 return w1_register_family(&w1_family_29);
400 static void __exit w1_f29_exit(void)
402 w1_unregister_family(&w1_family_29);
405 module_init(w1_f29_init);
406 module_exit(w1_f29_exit);