1
2
3
4
5
6
7
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
22MODULE_LICENSE("GPL");
23MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
24MODULE_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
30#define W1_F29_REG_OUTPUT_LATCH_STATE 0x89
31#define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A
32#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B
33#define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C
34#define W1_F29_REG_CONTROL_AND_STATUS 0x8D
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
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
45static 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->mutex);
56 dev_dbg(&sl->dev, "mutex locked");
57
58 if (w1_reset_select_slave(sl)) {
59 mutex_unlock(&sl->master->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->mutex);
70 dev_dbg(&sl->dev, "mutex unlocked");
71 return 1;
72}
73
74static 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
87static 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
101static 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
115static 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
129static 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
140static 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
154static 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->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
183
184
185
186 if (w1_reset_resume_command(sl->master))
187 goto error;
188
189 if (readBack != 0xAA) {
190
191 continue;
192 }
193
194
195
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
201 if (w1_read_8(sl->master) == *buf) {
202
203 mutex_unlock(&sl->master->mutex);
204 dev_dbg(&sl->dev,
205 "mutex unlocked, retries:%d", retries);
206 return 1;
207 }
208 }
209error:
210 mutex_unlock(&sl->master->mutex);
211 dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
212
213 return -EIO;
214}
215
216
217
218
219
220static 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->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->mutex);
240 return 1;
241 }
242 if (w1_reset_resume_command(sl->master))
243 goto error;
244 }
245
246error:
247 mutex_unlock(&sl->master->mutex);
248 return -EIO;
249}
250
251static 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->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
288 mutex_unlock(&sl->master->mutex);
289 return 1;
290 }
291 }
292error:
293 mutex_unlock(&sl->master->mutex);
294
295 return -EIO;
296}
297
298
299
300#define NB_SYSFS_BIN_FILES 6
301static 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 .write = 0,
336 },
337 {
338 .attr = {
339 .name = "cond_search_polarity",
340 .mode = S_IRUGO,
341 },
342 .size = 1,
343 .read = w1_f29_read_cond_search_polarity,
344 .write = 0,
345 },
346 {
347 .attr = {
348 .name = "status_control",
349 .mode = S_IRUGO | S_IWUSR | S_IWGRP,
350 },
351 .size = 1,
352 .read = w1_f29_read_status_control,
353 .write = w1_f29_write_status_control,
354 }
355};
356
357static int w1_f29_add_slave(struct w1_slave *sl)
358{
359 int err = 0;
360 int i;
361
362 for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
363 err = sysfs_create_bin_file(
364 &sl->dev.kobj,
365 &(w1_f29_sysfs_bin_files[i]));
366 if (err)
367 while (--i >= 0)
368 sysfs_remove_bin_file(&sl->dev.kobj,
369 &(w1_f29_sysfs_bin_files[i]));
370 return err;
371}
372
373static void w1_f29_remove_slave(struct w1_slave *sl)
374{
375 int i;
376 for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
377 sysfs_remove_bin_file(&sl->dev.kobj,
378 &(w1_f29_sysfs_bin_files[i]));
379}
380
381static struct w1_family_ops w1_f29_fops = {
382 .add_slave = w1_f29_add_slave,
383 .remove_slave = w1_f29_remove_slave,
384};
385
386static struct w1_family w1_family_29 = {
387 .fid = W1_FAMILY_DS2408,
388 .fops = &w1_f29_fops,
389};
390
391static int __init w1_f29_init(void)
392{
393 return w1_register_family(&w1_family_29);
394}
395
396static void __exit w1_f29_exit(void)
397{
398 w1_unregister_family(&w1_family_29);
399}
400
401module_init(w1_f29_init);
402module_exit(w1_f29_exit);
403