xref: /openbmc/linux/drivers/w1/slaves/w1_ds2408.c (revision 9d749629)
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 		/* 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 
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->bus_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->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--) {
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->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);
401