]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/w1/slaves/w1_ds2408.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[mirror_ubuntu-bionic-kernel.git] / drivers / w1 / slaves / w1_ds2408.c
CommitLineData
89610274
JFD
1/*
2 * w1_ds2408.c - w1 family 29 (DS2408) driver
3 *
4 * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
5 *
6 * This source code is licensed under the GNU General Public License,
7 * Version 2. See the file COPYING for more details.
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
de0d6dbd
AD
18#include <linux/w1.h>
19
20#define W1_FAMILY_DS2408 0x29
89610274 21
89610274
JFD
22#define W1_F29_RETRIES 3
23
24#define W1_F29_REG_LOGIG_STATE 0x88 /* R */
25#define W1_F29_REG_OUTPUT_LATCH_STATE 0x89 /* R */
26#define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A /* R */
27#define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
28#define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C /* RW */
29#define W1_F29_REG_CONTROL_AND_STATUS 0x8D /* RW */
30
31#define W1_F29_FUNC_READ_PIO_REGS 0xF0
32#define W1_F29_FUNC_CHANN_ACCESS_READ 0xF5
33#define W1_F29_FUNC_CHANN_ACCESS_WRITE 0x5A
34/* also used to write the control/status reg (0x8D): */
35#define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC
36#define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
37
38#define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA
39
40static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
41{
42 u8 wrbuf[3];
43 dev_dbg(&sl->dev,
44 "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
45 sl, (unsigned int)address, buf);
46
47 if (!buf)
48 return -EINVAL;
49
b02f8bed 50 mutex_lock(&sl->master->bus_mutex);
89610274
JFD
51 dev_dbg(&sl->dev, "mutex locked");
52
53 if (w1_reset_select_slave(sl)) {
b02f8bed 54 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
55 return -EIO;
56 }
57
58 wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS;
59 wrbuf[1] = address;
60 wrbuf[2] = 0;
61 w1_write_block(sl->master, wrbuf, 3);
62 *buf = w1_read_8(sl->master);
63
b02f8bed 64 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
65 dev_dbg(&sl->dev, "mutex unlocked");
66 return 1;
67}
68
32ea4175
GKH
69static ssize_t state_read(struct file *filp, struct kobject *kobj,
70 struct bin_attribute *bin_attr, char *buf, loff_t off,
71 size_t count)
89610274
JFD
72{
73 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
74 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
75 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
76 if (count != 1 || off != 0)
77 return -EFAULT;
78 return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
79}
80
32ea4175
GKH
81static ssize_t output_read(struct file *filp, struct kobject *kobj,
82 struct bin_attribute *bin_attr, char *buf,
83 loff_t off, size_t count)
89610274
JFD
84{
85 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
86 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
87 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
88 if (count != 1 || off != 0)
89 return -EFAULT;
90 return _read_reg(kobj_to_w1_slave(kobj),
91 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
92}
93
32ea4175
GKH
94static ssize_t activity_read(struct file *filp, struct kobject *kobj,
95 struct bin_attribute *bin_attr, char *buf,
96 loff_t off, size_t count)
89610274
JFD
97{
98 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
99 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
100 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
101 if (count != 1 || off != 0)
102 return -EFAULT;
103 return _read_reg(kobj_to_w1_slave(kobj),
104 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
105}
106
32ea4175
GKH
107static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
108 struct bin_attribute *bin_attr, char *buf,
109 loff_t off, size_t count)
89610274
JFD
110{
111 dev_dbg(&kobj_to_w1_slave(kobj)->dev,
112 "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
113 bin_attr->attr.name, kobj, (unsigned int)off, count, buf);
114 if (count != 1 || off != 0)
115 return -EFAULT;
116 return _read_reg(kobj_to_w1_slave(kobj),
117 W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
118}
119
32ea4175
GKH
120static ssize_t cond_search_polarity_read(struct file *filp,
121 struct kobject *kobj,
122 struct bin_attribute *bin_attr,
123 char *buf, loff_t off, size_t count)
89610274
JFD
124{
125 if (count != 1 || off != 0)
126 return -EFAULT;
127 return _read_reg(kobj_to_w1_slave(kobj),
128 W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
129}
130
32ea4175
GKH
131static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
132 struct bin_attribute *bin_attr, char *buf,
133 loff_t off, size_t count)
89610274
JFD
134{
135 if (count != 1 || off != 0)
136 return -EFAULT;
137 return _read_reg(kobj_to_w1_slave(kobj),
138 W1_F29_REG_CONTROL_AND_STATUS, buf);
139}
140
32ea4175
GKH
141static ssize_t output_write(struct file *filp, struct kobject *kobj,
142 struct bin_attribute *bin_attr, char *buf,
143 loff_t off, size_t count)
89610274
JFD
144{
145 struct w1_slave *sl = kobj_to_w1_slave(kobj);
146 u8 w1_buf[3];
147 u8 readBack;
148 unsigned int retries = W1_F29_RETRIES;
149
150 if (count != 1 || off != 0)
151 return -EFAULT;
152
153 dev_dbg(&sl->dev, "locking mutex for write_output");
b02f8bed 154 mutex_lock(&sl->master->bus_mutex);
89610274
JFD
155 dev_dbg(&sl->dev, "mutex locked");
156
157 if (w1_reset_select_slave(sl))
158 goto error;
159
160 while (retries--) {
161 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
162 w1_buf[1] = *buf;
163 w1_buf[2] = ~(*buf);
164 w1_write_block(sl->master, w1_buf, 3);
165
166 readBack = w1_read_8(sl->master);
aceca285
JFD
167
168 if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
169 if (w1_reset_resume_command(sl->master))
170 goto error;
171 /* try again, the slave is ready for a command */
172 continue;
173 }
174
175#ifdef CONFIG_W1_SLAVE_DS2408_READBACK
89610274
JFD
176 /* here the master could read another byte which
177 would be the PIO reg (the actual pin logic state)
178 since in this driver we don't know which pins are
179 in and outs, there's no value to read the state and
180 compare. with (*buf) so end this command abruptly: */
181 if (w1_reset_resume_command(sl->master))
182 goto error;
183
89610274
JFD
184 /* go read back the output latches */
185 /* (the direct effect of the write above) */
186 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
187 w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
188 w1_buf[2] = 0;
189 w1_write_block(sl->master, w1_buf, 3);
190 /* read the result of the READ_PIO_REGS command */
aceca285
JFD
191 if (w1_read_8(sl->master) == *buf)
192#endif
193 {
89610274 194 /* success! */
b02f8bed 195 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
196 dev_dbg(&sl->dev,
197 "mutex unlocked, retries:%d", retries);
198 return 1;
199 }
200 }
201error:
b02f8bed 202 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
203 dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
204
205 return -EIO;
206}
207
208
209/**
210 * Writing to the activity file resets the activity latches.
211 */
32ea4175
GKH
212static 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)
89610274
JFD
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
b02f8bed 222 mutex_lock(&sl->master->bus_mutex);
89610274
JFD
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) {
b02f8bed 230 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
231 return 1;
232 }
233 if (w1_reset_resume_command(sl->master))
234 goto error;
235 }
236
237error:
b02f8bed 238 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
239 return -EIO;
240}
241
32ea4175
GKH
242static 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)
89610274
JFD
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
b02f8bed 253 mutex_lock(&sl->master->bus_mutex);
89610274
JFD
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! */
b02f8bed 275 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
276 return 1;
277 }
278 }
279error:
b02f8bed 280 mutex_unlock(&sl->master->bus_mutex);
89610274
JFD
281
282 return -EIO;
283}
284
d5528773
JFD
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 */
291static 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);
89610274 301
d5528773
JFD
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);
308out:
309 mutex_unlock(&sl->master->bus_mutex);
310 return res;
311}
89610274 312
32ea4175
GKH
313static BIN_ATTR_RO(state, 1);
314static BIN_ATTR_RW(output, 1);
315static BIN_ATTR_RW(activity, 1);
316static BIN_ATTR_RO(cond_search_mask, 1);
317static BIN_ATTR_RO(cond_search_polarity, 1);
318static BIN_ATTR_RW(status_control, 1);
319
320static 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,
89610274
JFD
328};
329
32ea4175
GKH
330static const struct attribute_group w1_f29_group = {
331 .bin_attrs = w1_f29_bin_attrs,
332};
89610274 333
32ea4175
GKH
334static const struct attribute_group *w1_f29_groups[] = {
335 &w1_f29_group,
336 NULL,
337};
89610274
JFD
338
339static struct w1_family_ops w1_f29_fops = {
32ea4175
GKH
340 .add_slave = w1_f29_disable_test_mode,
341 .groups = w1_f29_groups,
89610274
JFD
342};
343
344static struct w1_family w1_family_29 = {
345 .fid = W1_FAMILY_DS2408,
346 .fops = &w1_f29_fops,
347};
939fc832 348module_w1_family(w1_family_29);
50fa2951
AD
349
350MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
351MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
352MODULE_LICENSE("GPL");
353MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));