xref: /linux/drivers/w1/slaves/w1_ds2408.c (revision ff5599816711d2e67da2d7561fd36ac48debd433)
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);
437