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
_read_reg(struct w1_slave * sl,u8 address,unsigned char * buf)38 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char *buf)
39 {
40 u8 wrbuf[3];
41
42 dev_dbg(&sl->dev, "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
state_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
output_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
activity_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
cond_search_mask_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
cond_search_polarity_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
status_control_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
optional_read_back_valid(struct w1_slave * sl,u8 expected)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
optional_read_back_valid(struct w1_slave * sl,u8 expected)156 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
157 {
158 return true;
159 }
160 #endif
161
output_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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 */
activity_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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
status_control_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)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 */
w1_f29_disable_test_mode(struct w1_slave * sl)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 const 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