]> Pileus Git - ~andy/linux/blob - drivers/w1/slaves/w1_ds2408.c
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[~andy/linux] / drivers / w1 / slaves / w1_ds2408.c
1 /*
2  *      w1_ds2408.c - w1 family 29 (DS2408) driver
3  *
4  * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
5  *
6  * This source code is licensed under the GNU General Public License,
7  * Version 2. See the file COPYING for more details.
8  */
9
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>
17
18 #include "../w1.h"
19 #include "../w1_int.h"
20 #include "../w1_family.h"
21
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));
26
27
28 #define W1_F29_RETRIES          3
29
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 */
36
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
43
44 #define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA
45
46 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
47 {
48         u8 wrbuf[3];
49         dev_dbg(&sl->dev,
50                         "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
51                         sl, (unsigned int)address, buf);
52
53         if (!buf)
54                 return -EINVAL;
55
56         mutex_lock(&sl->master->bus_mutex);
57         dev_dbg(&sl->dev, "mutex locked");
58
59         if (w1_reset_select_slave(sl)) {
60                 mutex_unlock(&sl->master->bus_mutex);
61                 return -EIO;
62         }
63
64         wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
65         wrbuf[1] = address;
66         wrbuf[2] = 0;
67         w1_write_block(sl->master, wrbuf, 3);
68         *buf = w1_read_8(sl->master);
69
70         mutex_unlock(&sl->master->bus_mutex);
71         dev_dbg(&sl->dev, "mutex unlocked");
72         return 1;
73 }
74
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)
79 {
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)
84                 return -EFAULT;
85         return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
86 }
87
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)
92 {
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)
97                 return -EFAULT;
98         return _read_reg(kobj_to_w1_slave(kobj),
99                                          W1_F29_REG_OUTPUT_LATCH_STATE, buf);
100 }
101
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)
106 {
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)
111                 return -EFAULT;
112         return _read_reg(kobj_to_w1_slave(kobj),
113                                          W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
114 }
115
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)
120 {
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)
125                 return -EFAULT;
126         return _read_reg(kobj_to_w1_slave(kobj),
127                 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
128 }
129
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)
134 {
135         if (count != 1 || off != 0)
136                 return -EFAULT;
137         return _read_reg(kobj_to_w1_slave(kobj),
138                 W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
139 }
140
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)
145 {
146         if (count != 1 || off != 0)
147                 return -EFAULT;
148         return _read_reg(kobj_to_w1_slave(kobj),
149                 W1_F29_REG_CONTROL_AND_STATUS, buf);
150 }
151
152
153
154
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)
159 {
160         struct w1_slave *sl = kobj_to_w1_slave(kobj);
161         u8 w1_buf[3];
162         u8 readBack;
163         unsigned int retries = W1_F29_RETRIES;
164
165         if (count != 1 || off != 0)
166                 return -EFAULT;
167
168         dev_dbg(&sl->dev, "locking mutex for write_output");
169         mutex_lock(&sl->master->bus_mutex);
170         dev_dbg(&sl->dev, "mutex locked");
171
172         if (w1_reset_select_slave(sl))
173                 goto error;
174
175         while (retries--) {
176                 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
177                 w1_buf[1] = *buf;
178                 w1_buf[2] = ~(*buf);
179                 w1_write_block(sl->master, w1_buf, 3);
180
181                 readBack = w1_read_8(sl->master);
182
183                 if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
184                         if (w1_reset_resume_command(sl->master))
185                                 goto error;
186                         /* try again, the slave is ready for a command */
187                         continue;
188                 }
189
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))
197                         goto error;
198
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;
203                 w1_buf[2] = 0;
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)
207 #endif
208                 {
209                         /* success! */
210                         mutex_unlock(&sl->master->bus_mutex);
211                         dev_dbg(&sl->dev,
212                                 "mutex unlocked, retries:%d", retries);
213                         return 1;
214                 }
215         }
216 error:
217         mutex_unlock(&sl->master->bus_mutex);
218         dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
219
220         return -EIO;
221 }
222
223
224 /**
225  * Writing to the activity file resets the activity latches.
226  */
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)
231 {
232         struct w1_slave *sl = kobj_to_w1_slave(kobj);
233         unsigned int retries = W1_F29_RETRIES;
234
235         if (count != 1 || off != 0)
236                 return -EFAULT;
237
238         mutex_lock(&sl->master->bus_mutex);
239
240         if (w1_reset_select_slave(sl))
241                 goto error;
242
243         while (retries--) {
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);
247                         return 1;
248                 }
249                 if (w1_reset_resume_command(sl->master))
250                         goto error;
251         }
252
253 error:
254         mutex_unlock(&sl->master->bus_mutex);
255         return -EIO;
256 }
257
258 static ssize_t w1_f29_write_status_control(
259         struct file *filp,
260         struct kobject *kobj,
261         struct bin_attribute *bin_attr,
262         char *buf,
263         loff_t off,
264         size_t count)
265 {
266         struct w1_slave *sl = kobj_to_w1_slave(kobj);
267         u8 w1_buf[4];
268         unsigned int retries = W1_F29_RETRIES;
269
270         if (count != 1 || off != 0)
271                 return -EFAULT;
272
273         mutex_lock(&sl->master->bus_mutex);
274
275         if (w1_reset_select_slave(sl))
276                 goto error;
277
278         while (retries--) {
279                 w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
280                 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
281                 w1_buf[2] = 0;
282                 w1_buf[3] = *buf;
283
284                 w1_write_block(sl->master, w1_buf, 4);
285                 if (w1_reset_resume_command(sl->master))
286                         goto error;
287
288                 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
289                 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
290                 w1_buf[2] = 0;
291
292                 w1_write_block(sl->master, w1_buf, 3);
293                 if (w1_read_8(sl->master) == *buf) {
294                         /* success! */
295                         mutex_unlock(&sl->master->bus_mutex);
296                         return 1;
297                 }
298         }
299 error:
300         mutex_unlock(&sl->master->bus_mutex);
301
302         return -EIO;
303 }
304
305 /*
306  * This is a special sequence we must do to ensure the P0 output is not stuck
307  * in test mode. This is described in rev 2 of the ds2408's datasheet
308  * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under
309  * "APPLICATION INFORMATION/Power-up timing".
310  */
311 static int w1_f29_disable_test_mode(struct w1_slave *sl)
312 {
313         int res;
314         u8 magic[10] = {0x96, };
315         u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
316
317         memcpy(&magic[1], &rn, 8);
318         magic[9] = 0x3C;
319
320         mutex_lock(&sl->master->bus_mutex);
321
322         res = w1_reset_bus(sl->master);
323         if (res)
324                 goto out;
325         w1_write_block(sl->master, magic, ARRAY_SIZE(magic));
326
327         res = w1_reset_bus(sl->master);
328 out:
329         mutex_unlock(&sl->master->bus_mutex);
330         return res;
331 }
332
333 static struct bin_attribute w1_f29_sysfs_bin_files[] = {
334         {
335                 .attr = {
336                         .name = "state",
337                         .mode = S_IRUGO,
338                 },
339                 .size = 1,
340                 .read = w1_f29_read_state,
341         },
342         {
343                 .attr = {
344                         .name = "output",
345                         .mode = S_IRUGO | S_IWUSR | S_IWGRP,
346                 },
347                 .size = 1,
348                 .read = w1_f29_read_output,
349                 .write = w1_f29_write_output,
350         },
351         {
352                 .attr = {
353                         .name = "activity",
354                         .mode = S_IRUGO,
355                 },
356                 .size = 1,
357                 .read = w1_f29_read_activity,
358                 .write = w1_f29_write_activity,
359         },
360         {
361                 .attr = {
362                         .name = "cond_search_mask",
363                         .mode = S_IRUGO,
364                 },
365                 .size = 1,
366                 .read = w1_f29_read_cond_search_mask,
367         },
368         {
369                 .attr = {
370                         .name = "cond_search_polarity",
371                         .mode = S_IRUGO,
372                 },
373                 .size = 1,
374                 .read = w1_f29_read_cond_search_polarity,
375         },
376         {
377                 .attr = {
378                         .name = "status_control",
379                         .mode = S_IRUGO | S_IWUSR | S_IWGRP,
380                 },
381                 .size = 1,
382                 .read = w1_f29_read_status_control,
383                 .write = w1_f29_write_status_control,
384         }
385 };
386
387 static int w1_f29_add_slave(struct w1_slave *sl)
388 {
389         int err = 0;
390         int i;
391
392         err = w1_f29_disable_test_mode(sl);
393         if (err)
394                 return err;
395
396         for (i = 0; i < ARRAY_SIZE(w1_f29_sysfs_bin_files) && !err; ++i)
397                 err = sysfs_create_bin_file(
398                         &sl->dev.kobj,
399                         &(w1_f29_sysfs_bin_files[i]));
400         if (err)
401                 while (--i >= 0)
402                         sysfs_remove_bin_file(&sl->dev.kobj,
403                                 &(w1_f29_sysfs_bin_files[i]));
404         return err;
405 }
406
407 static void w1_f29_remove_slave(struct w1_slave *sl)
408 {
409         int i;
410         for (i = ARRAY_SIZE(w1_f29_sysfs_bin_files) - 1; i >= 0; --i)
411                 sysfs_remove_bin_file(&sl->dev.kobj,
412                         &(w1_f29_sysfs_bin_files[i]));
413 }
414
415 static struct w1_family_ops w1_f29_fops = {
416         .add_slave      = w1_f29_add_slave,
417         .remove_slave   = w1_f29_remove_slave,
418 };
419
420 static struct w1_family w1_family_29 = {
421         .fid = W1_FAMILY_DS2408,
422         .fops = &w1_f29_fops,
423 };
424
425 static int __init w1_f29_init(void)
426 {
427         return w1_register_family(&w1_family_29);
428 }
429
430 static void __exit w1_f29_exit(void)
431 {
432         w1_unregister_family(&w1_family_29);
433 }
434
435 module_init(w1_f29_init);
436 module_exit(w1_f29_exit);