xref: /openbmc/linux/drivers/w1/slaves/w1_ds2408.c (revision f35e839a)
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->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),
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->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 
182 		if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
183 			if (w1_reset_resume_command(sl->master))
184 				goto error;
185 			/* try again, the slave is ready for a command */
186 			continue;
187 		}
188 
189 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK
190 		/* here the master could read another byte which
191 		   would be the PIO reg (the actual pin logic state)
192 		   since in this driver we don't know which pins are
193 		   in and outs, there's no value to read the state and
194 		   compare. with (*buf) so end this command abruptly: */
195 		if (w1_reset_resume_command(sl->master))
196 			goto error;
197 
198 		/* go read back the output latches */
199 		/* (the direct effect of the write above) */
200 		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
201 		w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
202 		w1_buf[2] = 0;
203 		w1_write_block(sl->master, w1_buf, 3);
204 		/* read the result of the READ_PIO_REGS command */
205 		if (w1_read_8(sl->master) == *buf)
206 #endif
207 		{
208 			/* success! */
209 			mutex_unlock(&sl->master->bus_mutex);
210 			dev_dbg(&sl->dev,
211 				"mutex unlocked, retries:%d", retries);
212 			return 1;
213 		}
214 	}
215 error:
216 	mutex_unlock(&sl->master->bus_mutex);
217 	dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
218 
219 	return -EIO;
220 }
221 
222 
223 /**
224  * Writing to the activity file resets the activity latches.
225  */
226 static ssize_t w1_f29_write_activity(
227 	struct file *filp, struct kobject *kobj,
228 	struct bin_attribute *bin_attr,
229 	char *buf, loff_t off, size_t count)
230 {
231 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
232 	unsigned int retries = W1_F29_RETRIES;
233 
234 	if (count != 1 || off != 0)
235 		return -EFAULT;
236 
237 	mutex_lock(&sl->master->bus_mutex);
238 
239 	if (w1_reset_select_slave(sl))
240 		goto error;
241 
242 	while (retries--) {
243 		w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
244 		if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
245 			mutex_unlock(&sl->master->bus_mutex);
246 			return 1;
247 		}
248 		if (w1_reset_resume_command(sl->master))
249 			goto error;
250 	}
251 
252 error:
253 	mutex_unlock(&sl->master->bus_mutex);
254 	return -EIO;
255 }
256 
257 static ssize_t w1_f29_write_status_control(
258 	struct file *filp,
259 	struct kobject *kobj,
260 	struct bin_attribute *bin_attr,
261 	char *buf,
262 	loff_t off,
263 	size_t count)
264 {
265 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
266 	u8 w1_buf[4];
267 	unsigned int retries = W1_F29_RETRIES;
268 
269 	if (count != 1 || off != 0)
270 		return -EFAULT;
271 
272 	mutex_lock(&sl->master->bus_mutex);
273 
274 	if (w1_reset_select_slave(sl))
275 		goto error;
276 
277 	while (retries--) {
278 		w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
279 		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
280 		w1_buf[2] = 0;
281 		w1_buf[3] = *buf;
282 
283 		w1_write_block(sl->master, w1_buf, 4);
284 		if (w1_reset_resume_command(sl->master))
285 			goto error;
286 
287 		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
288 		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
289 		w1_buf[2] = 0;
290 
291 		w1_write_block(sl->master, w1_buf, 3);
292 		if (w1_read_8(sl->master) == *buf) {
293 			/* success! */
294 			mutex_unlock(&sl->master->bus_mutex);
295 			return 1;
296 		}
297 	}
298 error:
299 	mutex_unlock(&sl->master->bus_mutex);
300 
301 	return -EIO;
302 }
303 
304 
305 
306 static struct bin_attribute w1_f29_sysfs_bin_files[] = {
307 	{
308 		.attr =	{
309 			.name = "state",
310 			.mode = S_IRUGO,
311 		},
312 		.size = 1,
313 		.read = w1_f29_read_state,
314 	},
315 	{
316 		.attr =	{
317 			.name = "output",
318 			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
319 		},
320 		.size = 1,
321 		.read = w1_f29_read_output,
322 		.write = w1_f29_write_output,
323 	},
324 	{
325 		.attr =	{
326 			.name = "activity",
327 			.mode = S_IRUGO,
328 		},
329 		.size = 1,
330 		.read = w1_f29_read_activity,
331 		.write = w1_f29_write_activity,
332 	},
333 	{
334 		.attr =	{
335 			.name = "cond_search_mask",
336 			.mode = S_IRUGO,
337 		},
338 		.size = 1,
339 		.read = w1_f29_read_cond_search_mask,
340 	},
341 	{
342 		.attr =	{
343 			.name = "cond_search_polarity",
344 			.mode = S_IRUGO,
345 		},
346 		.size = 1,
347 		.read = w1_f29_read_cond_search_polarity,
348 	},
349 	{
350 		.attr =	{
351 			.name = "status_control",
352 			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
353 		},
354 		.size = 1,
355 		.read = w1_f29_read_status_control,
356 		.write = w1_f29_write_status_control,
357 	}
358 };
359 
360 static int w1_f29_add_slave(struct w1_slave *sl)
361 {
362 	int err = 0;
363 	int i;
364 
365 	for (i = 0; i < ARRAY_SIZE(w1_f29_sysfs_bin_files) && !err; ++i)
366 		err = sysfs_create_bin_file(
367 			&sl->dev.kobj,
368 			&(w1_f29_sysfs_bin_files[i]));
369 	if (err)
370 		while (--i >= 0)
371 			sysfs_remove_bin_file(&sl->dev.kobj,
372 				&(w1_f29_sysfs_bin_files[i]));
373 	return err;
374 }
375 
376 static void w1_f29_remove_slave(struct w1_slave *sl)
377 {
378 	int i;
379 	for (i = ARRAY_SIZE(w1_f29_sysfs_bin_files) - 1; i >= 0; --i)
380 		sysfs_remove_bin_file(&sl->dev.kobj,
381 			&(w1_f29_sysfs_bin_files[i]));
382 }
383 
384 static struct w1_family_ops w1_f29_fops = {
385 	.add_slave      = w1_f29_add_slave,
386 	.remove_slave   = w1_f29_remove_slave,
387 };
388 
389 static struct w1_family w1_family_29 = {
390 	.fid = W1_FAMILY_DS2408,
391 	.fops = &w1_f29_fops,
392 };
393 
394 static int __init w1_f29_init(void)
395 {
396 	return w1_register_family(&w1_family_29);
397 }
398 
399 static void __exit w1_f29_exit(void)
400 {
401 	w1_unregister_family(&w1_family_29);
402 }
403 
404 module_init(w1_f29_init);
405 module_exit(w1_f29_exit);
406