w1: add 1-wire (w1) DS2408 8-Channel Addressable Switch support
[linux-2.6.git] / 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
26
27 #define W1_F29_RETRIES          3
28
29 #define W1_F29_REG_LOGIG_STATE             0x88 /* R */
30 #define W1_F29_REG_OUTPUT_LATCH_STATE      0x89 /* R */
31 #define W1_F29_REG_ACTIVITY_LATCH_STATE    0x8A /* R */
32 #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
33 #define W1_F29_REG_COND_SEARCH_POL_SELECT  0x8C /* RW */
34 #define W1_F29_REG_CONTROL_AND_STATUS      0x8D /* RW */
35
36 #define W1_F29_FUNC_READ_PIO_REGS          0xF0
37 #define W1_F29_FUNC_CHANN_ACCESS_READ      0xF5
38 #define W1_F29_FUNC_CHANN_ACCESS_WRITE     0x5A
39 /* also used to write the control/status reg (0x8D): */
40 #define W1_F29_FUNC_WRITE_COND_SEARCH_REG  0xCC
41 #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
42
43 #define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA
44
45 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
46 {
47         u8 wrbuf[3];
48         dev_dbg(&sl->dev,
49                         "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
50                         sl, (unsigned int)address, buf);
51
52         if (!buf)
53                 return -EINVAL;
54
55         mutex_lock(&sl->master->mutex);
56         dev_dbg(&sl->dev, "mutex locked");
57
58         if (w1_reset_select_slave(sl)) {
59                 mutex_unlock(&sl->master->mutex);
60                 return -EIO;
61         }
62
63         wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
64         wrbuf[1] = address;
65         wrbuf[2] = 0;
66         w1_write_block(sl->master, wrbuf, 3);
67         *buf = w1_read_8(sl->master);
68
69         mutex_unlock(&sl->master->mutex);
70         dev_dbg(&sl->dev, "mutex unlocked");
71         return 1;
72 }
73
74 static ssize_t w1_f29_read_state(
75         struct file *filp, struct kobject *kobj,
76         struct bin_attribute *bin_attr,
77         char *buf, loff_t off, size_t count)
78 {
79         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
80                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
81                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
82         if (count != 1 || off != 0)
83                 return -EFAULT;
84         return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
85 }
86
87 static ssize_t w1_f29_read_output(
88         struct file *filp, struct kobject *kobj,
89         struct bin_attribute *bin_attr,
90         char *buf, loff_t off, size_t count)
91 {
92         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
93                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
94                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
95         if (count != 1 || off != 0)
96                 return -EFAULT;
97         return _read_reg(kobj_to_w1_slave(kobj),
98                                          W1_F29_REG_OUTPUT_LATCH_STATE, buf);
99 }
100
101 static ssize_t w1_f29_read_activity(
102         struct file *filp, struct kobject *kobj,
103         struct bin_attribute *bin_attr,
104         char *buf, loff_t off, size_t count)
105 {
106         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
107                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
108                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
109         if (count != 1 || off != 0)
110                 return -EFAULT;
111         return _read_reg(kobj_to_w1_slave(kobj),
112                                          W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
113 }
114
115 static ssize_t w1_f29_read_cond_search_mask(
116         struct file *filp, struct kobject *kobj,
117         struct bin_attribute *bin_attr,
118         char *buf, loff_t off, size_t count)
119 {
120         dev_dbg(&kobj_to_w1_slave(kobj)->dev,
121                 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
122                 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
123         if (count != 1 || off != 0)
124                 return -EFAULT;
125         return _read_reg(kobj_to_w1_slave(kobj),
126                 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
127 }
128
129 static ssize_t w1_f29_read_cond_search_polarity(
130         struct file *filp, struct kobject *kobj,
131         struct bin_attribute *bin_attr,
132         char *buf, loff_t off, size_t count)
133 {
134         if (count != 1 || off != 0)
135                 return -EFAULT;
136         return _read_reg(kobj_to_w1_slave(kobj),
137                 W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
138 }
139
140 static ssize_t w1_f29_read_status_control(
141         struct file *filp, struct kobject *kobj,
142         struct bin_attribute *bin_attr,
143         char *buf, loff_t off, size_t count)
144 {
145         if (count != 1 || off != 0)
146                 return -EFAULT;
147         return _read_reg(kobj_to_w1_slave(kobj),
148                 W1_F29_REG_CONTROL_AND_STATUS, buf);
149 }
150
151
152
153
154 static ssize_t w1_f29_write_output(
155         struct file *filp, struct kobject *kobj,
156         struct bin_attribute *bin_attr,
157         char *buf, loff_t off, size_t count)
158 {
159         struct w1_slave *sl = kobj_to_w1_slave(kobj);
160         u8 w1_buf[3];
161         u8 readBack;
162         unsigned int retries = W1_F29_RETRIES;
163
164         if (count != 1 || off != 0)
165                 return -EFAULT;
166
167         dev_dbg(&sl->dev, "locking mutex for write_output");
168         mutex_lock(&sl->master->mutex);
169         dev_dbg(&sl->dev, "mutex locked");
170
171         if (w1_reset_select_slave(sl))
172                 goto error;
173
174         while (retries--) {
175                 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
176                 w1_buf[1] = *buf;
177                 w1_buf[2] = ~(*buf);
178                 w1_write_block(sl->master, w1_buf, 3);
179
180                 readBack = w1_read_8(sl->master);
181                 /* here the master could read another byte which
182                    would be the PIO reg (the actual pin logic state)
183                    since in this driver we don't know which pins are
184                    in and outs, there's no value to read the state and
185                    compare. with (*buf) so end this command abruptly: */
186                 if (w1_reset_resume_command(sl->master))
187                         goto error;
188
189                 if (readBack != 0xAA) {
190                         /* try again, the slave is ready for a command */
191                         continue;
192                 }
193
194                 /* go read back the output latches */
195                 /* (the direct effect of the write above) */
196                 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
197                 w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
198                 w1_buf[2] = 0;
199                 w1_write_block(sl->master, w1_buf, 3);
200                 /* read the result of the READ_PIO_REGS command */
201                 if (w1_read_8(sl->master) == *buf) {
202                         /* success! */
203                         mutex_unlock(&sl->master->mutex);
204                         dev_dbg(&sl->dev,
205                                 "mutex unlocked, retries:%d", retries);
206                         return 1;
207                 }
208         }
209 error:
210         mutex_unlock(&sl->master->mutex);
211         dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
212
213         return -EIO;
214 }
215
216
217 /**
218  * Writing to the activity file resets the activity latches.
219  */
220 static ssize_t w1_f29_write_activity(
221         struct file *filp, struct kobject *kobj,
222         struct bin_attribute *bin_attr,
223         char *buf, loff_t off, size_t count)
224 {
225         struct w1_slave *sl = kobj_to_w1_slave(kobj);
226         unsigned int retries = W1_F29_RETRIES;
227
228         if (count != 1 || off != 0)
229                 return -EFAULT;
230
231         mutex_lock(&sl->master->mutex);
232
233         if (w1_reset_select_slave(sl))
234                 goto error;
235
236         while (retries--) {
237                 w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
238                 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
239                         mutex_unlock(&sl->master->mutex);
240                         return 1;
241                 }
242                 if (w1_reset_resume_command(sl->master))
243                         goto error;
244         }
245
246 error:
247         mutex_unlock(&sl->master->mutex);
248         return -EIO;
249 }
250
251 static ssize_t w1_f29_write_status_control(
252         struct file *filp,
253         struct kobject *kobj,
254         struct bin_attribute *bin_attr,
255         char *buf,
256         loff_t off,
257         size_t count)
258 {
259         struct w1_slave *sl = kobj_to_w1_slave(kobj);
260         u8 w1_buf[4];
261         unsigned int retries = W1_F29_RETRIES;
262
263         if (count != 1 || off != 0)
264                 return -EFAULT;
265
266         mutex_lock(&sl->master->mutex);
267
268         if (w1_reset_select_slave(sl))
269                 goto error;
270
271         while (retries--) {
272                 w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
273                 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
274                 w1_buf[2] = 0;
275                 w1_buf[3] = *buf;
276
277                 w1_write_block(sl->master, w1_buf, 4);
278                 if (w1_reset_resume_command(sl->master))
279                         goto error;
280
281                 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
282                 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
283                 w1_buf[2] = 0;
284
285                 w1_write_block(sl->master, w1_buf, 3);
286                 if (w1_read_8(sl->master) == *buf) {
287                         /* success! */
288                         mutex_unlock(&sl->master->mutex);
289                         return 1;
290                 }
291         }
292 error:
293         mutex_unlock(&sl->master->mutex);
294
295         return -EIO;
296 }
297
298
299
300 #define NB_SYSFS_BIN_FILES 6
301 static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
302         {
303                 .attr = {
304                         .name = "state",
305                         .mode = S_IRUGO,
306                 },
307                 .size = 1,
308                 .read = w1_f29_read_state,
309         },
310         {
311                 .attr = {
312                         .name = "output",
313                         .mode = S_IRUGO | S_IWUSR | S_IWGRP,
314                 },
315                 .size = 1,
316                 .read = w1_f29_read_output,
317                 .write = w1_f29_write_output,
318         },
319         {
320                 .attr = {
321                         .name = "activity",
322                         .mode = S_IRUGO,
323                 },
324                 .size = 1,
325                 .read = w1_f29_read_activity,
326                 .write = w1_f29_write_activity,
327         },
328         {
329                 .attr = {
330                         .name = "cond_search_mask",
331                         .mode = S_IRUGO,
332                 },
333                 .size = 1,
334                 .read = w1_f29_read_cond_search_mask,
335                 .write = 0,
336         },
337         {
338                 .attr = {
339                         .name = "cond_search_polarity",
340                         .mode = S_IRUGO,
341                 },
342                 .size = 1,
343                 .read = w1_f29_read_cond_search_polarity,
344                 .write = 0,
345         },
346         {
347                 .attr = {
348                         .name = "status_control",
349                         .mode = S_IRUGO | S_IWUSR | S_IWGRP,
350                 },
351                 .size = 1,
352                 .read = w1_f29_read_status_control,
353                 .write = w1_f29_write_status_control,
354         }
355 };
356
357 static int w1_f29_add_slave(struct w1_slave *sl)
358 {
359         int err = 0;
360         int i;
361
362         for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
363                 err = sysfs_create_bin_file(
364                         &sl->dev.kobj,
365                         &(w1_f29_sysfs_bin_files[i]));
366         if (err)
367                 while (--i >= 0)
368                         sysfs_remove_bin_file(&sl->dev.kobj,
369                                 &(w1_f29_sysfs_bin_files[i]));
370         return err;
371 }
372
373 static void w1_f29_remove_slave(struct w1_slave *sl)
374 {
375         int i;
376         for (i = NB_SYSFS_BIN_FILES; i <= 0; --i)
377                 sysfs_remove_bin_file(&sl->dev.kobj,
378                         &(w1_f29_sysfs_bin_files[i]));
379 }
380
381 static struct w1_family_ops w1_f29_fops = {
382         .add_slave      = w1_f29_add_slave,
383         .remove_slave   = w1_f29_remove_slave,
384 };
385
386 static struct w1_family w1_family_29 = {
387         .fid = W1_FAMILY_DS2408,
388         .fops = &w1_f29_fops,
389 };
390
391 static int __init w1_f29_init(void)
392 {
393         return w1_register_family(&w1_family_29);
394 }
395
396 static void __exit w1_f29_exit(void)
397 {
398         w1_unregister_family(&w1_family_29);
399 }
400
401 module_init(w1_f29_init);
402 module_exit(w1_f29_exit);