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");
25MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));
26
27
28#define W1_F29_RETRIES 3
29
30#define W1_F29_REG_LOGIG_STATE 0x88
31#define W1_F29_REG_OUTPUT_LATCH_STATE 0x89
32#define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A
33#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B
34#define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C
35#define W1_F29_REG_CONTROL_AND_STATUS 0x8D
36
37#define W1_F29_FUNC_READ_PIO_REGS 0xF0
38#define W1_F29_FUNC_CHANN_ACCESS_READ 0xF5
39#define W1_F29_FUNC_CHANN_ACCESS_WRITE 0x5A
40
41#define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC
42#define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
43
44#define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA
45
46static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
47{
48 u8 wrbuf[3];
49 dev_dbg(&sl->dev,
50 "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
51 sl, (unsigned int)address, buf);
52
53 if (!buf)
54 return -EINVAL;
55
56 mutex_lock(&sl->master->bus_mutex);
57 dev_dbg(&sl->dev, "mutex locked");
58
59 if (w1_reset_select_slave(sl)) {
60 mutex_unlock(&sl->master->bus_mutex);
61 return -EIO;
62 }
63
64 wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
65 wrbuf[1] = address;
66 wrbuf[2] = 0;
67 w1_write_block(sl->master, wrbuf, 3);
68 *buf = w1_read_8(sl->master);
69
70 mutex_unlock(&sl->master->bus_mutex);
71 dev_dbg(&sl->dev, "mutex unlocked");
72 return 1;
73}
74
75static ssize_t state_read(struct file *filp, struct kobject *kobj,
76 struct bin_attribute *bin_attr, char *buf, loff_t off,
77 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 output_read(struct file *filp, struct kobject *kobj,
88 struct bin_attribute *bin_attr, char *buf,
89 loff_t off, size_t count)
90{
91 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
92 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
93 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
94 if (count != 1 || off != 0)
95 return -EFAULT;
96 return _read_reg(kobj_to_w1_slave(kobj),
97 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
98}
99
100static ssize_t activity_read(struct file *filp, struct kobject *kobj,
101 struct bin_attribute *bin_attr, char *buf,
102 loff_t off, size_t count)
103{
104 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
105 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
106 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
107 if (count != 1 || off != 0)
108 return -EFAULT;
109 return _read_reg(kobj_to_w1_slave(kobj),
110 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
111}
112
113static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
114 struct bin_attribute *bin_attr, char *buf,
115 loff_t off, size_t count)
116{
117 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
118 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
119 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
120 if (count != 1 || off != 0)
121 return -EFAULT;
122 return _read_reg(kobj_to_w1_slave(kobj),
123 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
124}
125
126static ssize_t cond_search_polarity_read(struct file *filp,
127 struct kobject *kobj,
128 struct bin_attribute *bin_attr,
129 char *buf, loff_t off, size_t count)
130{
131 if (count != 1 || off != 0)
132 return -EFAULT;
133 return _read_reg(kobj_to_w1_slave(kobj),
134 W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
135}
136
137static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
138 struct bin_attribute *bin_attr, char *buf,
139 loff_t off, size_t count)
140{
141 if (count != 1 || off != 0)
142 return -EFAULT;
143 return _read_reg(kobj_to_w1_slave(kobj),
144 W1_F29_REG_CONTROL_AND_STATUS, buf);
145}
146
147static ssize_t output_write(struct file *filp, struct kobject *kobj,
148 struct bin_attribute *bin_attr, char *buf,
149 loff_t off, size_t count)
150{
151 struct w1_slave *sl = kobj_to_w1_slave(kobj);
152 u8 w1_buf[3];
153 u8 readBack;
154 unsigned int retries = W1_F29_RETRIES;
155
156 if (count != 1 || off != 0)
157 return -EFAULT;
158
159 dev_dbg(&sl->dev, "locking mutex for write_output");
160 mutex_lock(&sl->master->bus_mutex);
161 dev_dbg(&sl->dev, "mutex locked");
162
163 if (w1_reset_select_slave(sl))
164 goto error;
165
166 while (retries--) {
167 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
168 w1_buf[1] = *buf;
169 w1_buf[2] = ~(*buf);
170 w1_write_block(sl->master, w1_buf, 3);
171
172 readBack = w1_read_8(sl->master);
173
174 if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
175 if (w1_reset_resume_command(sl->master))
176 goto error;
177
178 continue;
179 }
180
181#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
182
183
184
185
186
187 if (w1_reset_resume_command(sl->master))
188 goto error;
189
190
191
192 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
193 w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
194 w1_buf[2] = 0;
195 w1_write_block(sl->master, w1_buf, 3);
196
197 if (w1_read_8(sl->master) == *buf)
198#endif
199 {
200
201 mutex_unlock(&sl->master->bus_mutex);
202 dev_dbg(&sl->dev,
203 "mutex unlocked, retries:%d", retries);
204 return 1;
205 }
206 }
207error:
208 mutex_unlock(&sl->master->bus_mutex);
209 dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
210
211 return -EIO;
212}
213
214
215
216
217
218static ssize_t activity_write(struct file *filp, struct kobject *kobj,
219 struct bin_attribute *bin_attr, char *buf,
220 loff_t off, size_t count)
221{
222 struct w1_slave *sl = kobj_to_w1_slave(kobj);
223 unsigned int retries = W1_F29_RETRIES;
224
225 if (count != 1 || off != 0)
226 return -EFAULT;
227
228 mutex_lock(&sl->master->bus_mutex);
229
230 if (w1_reset_select_slave(sl))
231 goto error;
232
233 while (retries--) {
234 w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
235 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
236 mutex_unlock(&sl->master->bus_mutex);
237 return 1;
238 }
239 if (w1_reset_resume_command(sl->master))
240 goto error;
241 }
242
243error:
244 mutex_unlock(&sl->master->bus_mutex);
245 return -EIO;
246}
247
248static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
249 struct bin_attribute *bin_attr, char *buf,
250 loff_t off, size_t count)
251{
252 struct w1_slave *sl = kobj_to_w1_slave(kobj);
253 u8 w1_buf[4];
254 unsigned int retries = W1_F29_RETRIES;
255
256 if (count != 1 || off != 0)
257 return -EFAULT;
258
259 mutex_lock(&sl->master->bus_mutex);
260
261 if (w1_reset_select_slave(sl))
262 goto error;
263
264 while (retries--) {
265 w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
266 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
267 w1_buf[2] = 0;
268 w1_buf[3] = *buf;
269
270 w1_write_block(sl->master, w1_buf, 4);
271 if (w1_reset_resume_command(sl->master))
272 goto error;
273
274 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
275 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
276 w1_buf[2] = 0;
277
278 w1_write_block(sl->master, w1_buf, 3);
279 if (w1_read_8(sl->master) == *buf) {
280
281 mutex_unlock(&sl->master->bus_mutex);
282 return 1;
283 }
284 }
285error:
286 mutex_unlock(&sl->master->bus_mutex);
287
288 return -EIO;
289}
290
291
292
293
294
295
296
297static int w1_f29_disable_test_mode(struct w1_slave *sl)
298{
299 int res;
300 u8 magic[10] = {0x96, };
301 u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
302
303 memcpy(&magic[1], &rn, 8);
304 magic[9] = 0x3C;
305
306 mutex_lock(&sl->master->bus_mutex);
307
308 res = w1_reset_bus(sl->master);
309 if (res)
310 goto out;
311 w1_write_block(sl->master, magic, ARRAY_SIZE(magic));
312
313 res = w1_reset_bus(sl->master);
314out:
315 mutex_unlock(&sl->master->bus_mutex);
316 return res;
317}
318
319static BIN_ATTR_RO(state, 1);
320static BIN_ATTR_RW(output, 1);
321static BIN_ATTR_RW(activity, 1);
322static BIN_ATTR_RO(cond_search_mask, 1);
323static BIN_ATTR_RO(cond_search_polarity, 1);
324static BIN_ATTR_RW(status_control, 1);
325
326static struct bin_attribute *w1_f29_bin_attrs[] = {
327 &bin_attr_state,
328 &bin_attr_output,
329 &bin_attr_activity,
330 &bin_attr_cond_search_mask,
331 &bin_attr_cond_search_polarity,
332 &bin_attr_status_control,
333 NULL,
334};
335
336static const struct attribute_group w1_f29_group = {
337 .bin_attrs = w1_f29_bin_attrs,
338};
339
340static const struct attribute_group *w1_f29_groups[] = {
341 &w1_f29_group,
342 NULL,
343};
344
345static struct w1_family_ops w1_f29_fops = {
346 .add_slave = w1_f29_disable_test_mode,
347 .groups = w1_f29_groups,
348};
349
350static struct w1_family w1_family_29 = {
351 .fid = W1_FAMILY_DS2408,
352 .fops = &w1_f29_fops,
353};
354
355static int __init w1_f29_init(void)
356{
357 return w1_register_family(&w1_family_29);
358}
359
360static void __exit w1_f29_exit(void)
361{
362 w1_unregister_family(&w1_family_29);
363}
364
365module_init(w1_f29_init);
366module_exit(w1_f29_exit);
367