Linux-libre 5.7.6-gnu
[librecmc/linux-libre.git] / drivers / w1 / slaves / w1_ds2408.c
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));