xref: /openbmc/linux/drivers/w1/slaves/w1_ds2408.c (revision 9726bfcd)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *	w1_ds2408.c - w1 family 29 (DS2408) driver
4  *
5  * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/device.h>
12 #include <linux/types.h>
13 #include <linux/delay.h>
14 #include <linux/slab.h>
15 
16 #include <linux/w1.h>
17 
18 #define W1_FAMILY_DS2408	0x29
19 
20 #define W1_F29_RETRIES		3
21 
22 #define W1_F29_REG_LOGIG_STATE             0x88 /* R */
23 #define W1_F29_REG_OUTPUT_LATCH_STATE      0x89 /* R */
24 #define W1_F29_REG_ACTIVITY_LATCH_STATE    0x8A /* R */
25 #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
26 #define W1_F29_REG_COND_SEARCH_POL_SELECT  0x8C /* RW */
27 #define W1_F29_REG_CONTROL_AND_STATUS      0x8D /* RW */
28 
29 #define W1_F29_FUNC_READ_PIO_REGS          0xF0
30 #define W1_F29_FUNC_CHANN_ACCESS_READ      0xF5
31 #define W1_F29_FUNC_CHANN_ACCESS_WRITE     0x5A
32 /* also used to write the control/status reg (0x8D): */
33 #define W1_F29_FUNC_WRITE_COND_SEARCH_REG  0xCC
34 #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
35 
36 #define W1_F29_SUCCESS_CONFIRM_BYTE        0xAA
37 
38 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
39 {
40 	u8 wrbuf[3];
41 	dev_dbg(&sl->dev,
42 			"Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
43 			sl, (unsigned int)address, buf);
44 
45 	if (!buf)
46 		return -EINVAL;
47 
48 	mutex_lock(&sl->master->bus_mutex);
49 	dev_dbg(&sl->dev, "mutex locked");
50 
51 	if (w1_reset_select_slave(sl)) {
52 		mutex_unlock(&sl->master->bus_mutex);
53 		return -EIO;
54 	}
55 
56 	wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
57 	wrbuf[1] = address;
58 	wrbuf[2] = 0;
59 	w1_write_block(sl->master, wrbuf, 3);
60 	*buf = w1_read_8(sl->master);
61 
62 	mutex_unlock(&sl->master->bus_mutex);
63 	dev_dbg(&sl->dev, "mutex unlocked");
64 	return 1;
65 }
66 
67 static ssize_t state_read(struct file *filp, struct kobject *kobj,
68 			  struct bin_attribute *bin_attr, char *buf, loff_t off,
69 			  size_t count)
70 {
71 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
72 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
73 		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
74 	if (count != 1 || off != 0)
75 		return -EFAULT;
76 	return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
77 }
78 
79 static ssize_t output_read(struct file *filp, struct kobject *kobj,
80 			   struct bin_attribute *bin_attr, char *buf,
81 			   loff_t off, size_t count)
82 {
83 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
84 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
85 		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
86 	if (count != 1 || off != 0)
87 		return -EFAULT;
88 	return _read_reg(kobj_to_w1_slave(kobj),
89 					 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
90 }
91 
92 static ssize_t activity_read(struct file *filp, struct kobject *kobj,
93 			     struct bin_attribute *bin_attr, char *buf,
94 			     loff_t off, size_t count)
95 {
96 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
97 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
98 		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
99 	if (count != 1 || off != 0)
100 		return -EFAULT;
101 	return _read_reg(kobj_to_w1_slave(kobj),
102 					 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
103 }
104 
105 static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
106 				     struct bin_attribute *bin_attr, char *buf,
107 				     loff_t off, size_t count)
108 {
109 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
110 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
111 		bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
112 	if (count != 1 || off != 0)
113 		return -EFAULT;
114 	return _read_reg(kobj_to_w1_slave(kobj),
115 		W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
116 }
117 
118 static ssize_t cond_search_polarity_read(struct file *filp,
119 					 struct kobject *kobj,
120 					 struct bin_attribute *bin_attr,
121 					 char *buf, loff_t off, size_t count)
122 {
123 	if (count != 1 || off != 0)
124 		return -EFAULT;
125 	return _read_reg(kobj_to_w1_slave(kobj),
126 		W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
127 }
128 
129 static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
130 				   struct bin_attribute *bin_attr, char *buf,
131 				   loff_t off, size_t count)
132 {
133 	if (count != 1 || off != 0)
134 		return -EFAULT;
135 	return _read_reg(kobj_to_w1_slave(kobj),
136 		W1_F29_REG_CONTROL_AND_STATUS, buf);
137 }
138 
139 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK
140 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
141 {
142 	u8 w1_buf[3];
143 
144 	if (w1_reset_resume_command(sl->master))
145 		return false;
146 
147 	w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
148 	w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
149 	w1_buf[2] = 0;
150 
151 	w1_write_block(sl->master, w1_buf, 3);
152 
153 	return (w1_read_8(sl->master) == expected);
154 }
155 #else
156 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
157 {
158 	return true;
159 }
160 #endif
161 
162 static ssize_t output_write(struct file *filp, struct kobject *kobj,
163 			    struct bin_attribute *bin_attr, char *buf,
164 			    loff_t off, size_t count)
165 {
166 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
167 	u8 w1_buf[3];
168 	unsigned int retries = W1_F29_RETRIES;
169 	ssize_t bytes_written = -EIO;
170 
171 	if (count != 1 || off != 0)
172 		return -EFAULT;
173 
174 	dev_dbg(&sl->dev, "locking mutex for write_output");
175 	mutex_lock(&sl->master->bus_mutex);
176 	dev_dbg(&sl->dev, "mutex locked");
177 
178 	if (w1_reset_select_slave(sl))
179 		goto out;
180 
181 	do {
182 		w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
183 		w1_buf[1] = *buf;
184 		w1_buf[2] = ~(*buf);
185 
186 		w1_write_block(sl->master, w1_buf, 3);
187 
188 		if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
189 		    optional_read_back_valid(sl, *buf)) {
190 			bytes_written = 1;
191 			goto out;
192 		}
193 
194 		if (w1_reset_resume_command(sl->master))
195 			goto out; /* unrecoverable error */
196 		/* try again, the slave is ready for a command */
197 	} while (--retries);
198 
199 out:
200 	mutex_unlock(&sl->master->bus_mutex);
201 
202 	dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
203 		(bytes_written > 0) ? "succeeded" : "error", retries);
204 
205 	return bytes_written;
206 }
207 
208 
209 /**
210  * Writing to the activity file resets the activity latches.
211  */
212 static ssize_t activity_write(struct file *filp, struct kobject *kobj,
213 			      struct bin_attribute *bin_attr, char *buf,
214 			      loff_t off, size_t count)
215 {
216 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
217 	unsigned int retries = W1_F29_RETRIES;
218 
219 	if (count != 1 || off != 0)
220 		return -EFAULT;
221 
222 	mutex_lock(&sl->master->bus_mutex);
223 
224 	if (w1_reset_select_slave(sl))
225 		goto error;
226 
227 	while (retries--) {
228 		w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
229 		if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
230 			mutex_unlock(&sl->master->bus_mutex);
231 			return 1;
232 		}
233 		if (w1_reset_resume_command(sl->master))
234 			goto error;
235 	}
236 
237 error:
238 	mutex_unlock(&sl->master->bus_mutex);
239 	return -EIO;
240 }
241 
242 static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
243 				    struct bin_attribute *bin_attr, char *buf,
244 				    loff_t off, size_t count)
245 {
246 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
247 	u8 w1_buf[4];
248 	unsigned int retries = W1_F29_RETRIES;
249 
250 	if (count != 1 || off != 0)
251 		return -EFAULT;
252 
253 	mutex_lock(&sl->master->bus_mutex);
254 
255 	if (w1_reset_select_slave(sl))
256 		goto error;
257 
258 	while (retries--) {
259 		w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
260 		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
261 		w1_buf[2] = 0;
262 		w1_buf[3] = *buf;
263 
264 		w1_write_block(sl->master, w1_buf, 4);
265 		if (w1_reset_resume_command(sl->master))
266 			goto error;
267 
268 		w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
269 		w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
270 		w1_buf[2] = 0;
271 
272 		w1_write_block(sl->master, w1_buf, 3);
273 		if (w1_read_8(sl->master) == *buf) {
274 			/* success! */
275 			mutex_unlock(&sl->master->bus_mutex);
276 			return 1;
277 		}
278 	}
279 error:
280 	mutex_unlock(&sl->master->bus_mutex);
281 
282 	return -EIO;
283 }
284 
285 /*
286  * This is a special sequence we must do to ensure the P0 output is not stuck
287  * in test mode. This is described in rev 2 of the ds2408's datasheet
288  * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under
289  * "APPLICATION INFORMATION/Power-up timing".
290  */
291 static int w1_f29_disable_test_mode(struct w1_slave *sl)
292 {
293 	int res;
294 	u8 magic[10] = {0x96, };
295 	u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
296 
297 	memcpy(&magic[1], &rn, 8);
298 	magic[9] = 0x3C;
299 
300 	mutex_lock(&sl->master->bus_mutex);
301 
302 	res = w1_reset_bus(sl->master);
303 	if (res)
304 		goto out;
305 	w1_write_block(sl->master, magic, ARRAY_SIZE(magic));
306 
307 	res = w1_reset_bus(sl->master);
308 out:
309 	mutex_unlock(&sl->master->bus_mutex);
310 	return res;
311 }
312 
313 static BIN_ATTR_RO(state, 1);
314 static BIN_ATTR_RW(output, 1);
315 static BIN_ATTR_RW(activity, 1);
316 static BIN_ATTR_RO(cond_search_mask, 1);
317 static BIN_ATTR_RO(cond_search_polarity, 1);
318 static BIN_ATTR_RW(status_control, 1);
319 
320 static struct bin_attribute *w1_f29_bin_attrs[] = {
321 	&bin_attr_state,
322 	&bin_attr_output,
323 	&bin_attr_activity,
324 	&bin_attr_cond_search_mask,
325 	&bin_attr_cond_search_polarity,
326 	&bin_attr_status_control,
327 	NULL,
328 };
329 
330 static const struct attribute_group w1_f29_group = {
331 	.bin_attrs = w1_f29_bin_attrs,
332 };
333 
334 static const struct attribute_group *w1_f29_groups[] = {
335 	&w1_f29_group,
336 	NULL,
337 };
338 
339 static struct w1_family_ops w1_f29_fops = {
340 	.add_slave      = w1_f29_disable_test_mode,
341 	.groups		= w1_f29_groups,
342 };
343 
344 static struct w1_family w1_family_29 = {
345 	.fid = W1_FAMILY_DS2408,
346 	.fops = &w1_f29_fops,
347 };
348 module_w1_family(w1_family_29);
349 
350 MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
351 MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
352 MODULE_LICENSE("GPL");
353 MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));
354