Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
w1_ds2408.c
Go to the documentation of this file.
1 /*
2  * w1_ds2408.c - w1 family 29 (DS2408) driver
3  *
4  * Copyright (c) 2010 Jean-Francois Dagenais <[email protected]>
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 <[email protected]>");
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->bus_mutex);
56  dev_dbg(&sl->dev, "mutex locked");
57 
58  if (w1_reset_select_slave(sl)) {
59  mutex_unlock(&sl->master->bus_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->bus_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),
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),
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),
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),
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),
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->bus_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->bus_mutex);
204  dev_dbg(&sl->dev,
205  "mutex unlocked, retries:%d", retries);
206  return 1;
207  }
208  }
209 error:
210  mutex_unlock(&sl->master->bus_mutex);
211  dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
212 
213  return -EIO;
214 }
215 
216 
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->bus_mutex);
232 
233  if (w1_reset_select_slave(sl))
234  goto error;
235 
236  while (retries--) {
238  if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
239  mutex_unlock(&sl->master->bus_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->bus_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->bus_mutex);
267 
268  if (w1_reset_select_slave(sl))
269  goto error;
270 
271  while (retries--) {
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->bus_mutex);
289  return 1;
290  }
291  }
292 error:
293  mutex_unlock(&sl->master->bus_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  },
336  {
337  .attr = {
338  .name = "cond_search_polarity",
339  .mode = S_IRUGO,
340  },
341  .size = 1,
342  .read = w1_f29_read_cond_search_polarity,
343  },
344  {
345  .attr = {
346  .name = "status_control",
347  .mode = S_IRUGO | S_IWUSR | S_IWGRP,
348  },
349  .size = 1,
350  .read = w1_f29_read_status_control,
351  .write = w1_f29_write_status_control,
352  }
353 };
354 
355 static int w1_f29_add_slave(struct w1_slave *sl)
356 {
357  int err = 0;
358  int i;
359 
360  for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
361  err = sysfs_create_bin_file(
362  &sl->dev.kobj,
363  &(w1_f29_sysfs_bin_files[i]));
364  if (err)
365  while (--i >= 0)
366  sysfs_remove_bin_file(&sl->dev.kobj,
367  &(w1_f29_sysfs_bin_files[i]));
368  return err;
369 }
370 
371 static void w1_f29_remove_slave(struct w1_slave *sl)
372 {
373  int i;
374  for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
375  sysfs_remove_bin_file(&sl->dev.kobj,
376  &(w1_f29_sysfs_bin_files[i]));
377 }
378 
379 static struct w1_family_ops w1_f29_fops = {
380  .add_slave = w1_f29_add_slave,
381  .remove_slave = w1_f29_remove_slave,
382 };
383 
384 static struct w1_family w1_family_29 = {
385  .fid = W1_FAMILY_DS2408,
386  .fops = &w1_f29_fops,
387 };
388 
389 static int __init w1_f29_init(void)
390 {
391  return w1_register_family(&w1_family_29);
392 }
393 
394 static void __exit w1_f29_exit(void)
395 {
396  w1_unregister_family(&w1_family_29);
397 }
398 
399 module_init(w1_f29_init);
400 module_exit(w1_f29_exit);