ACPI / init: Switch over platform to the ACPI mode later
[linux/fpc-iii.git] / drivers / w1 / slaves / w1_ds2408.c
blob7dfa0e11688a1c93b4e466522ec4ccd1e2b59250
1 /*
2 * w1_ds2408.c - w1 family 29 (DS2408) driver
4 * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com>
6 * This source code is licensed under the GNU General Public License,
7 * Version 2. See the file COPYING for more details.
8 */
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>
18 #include "../w1.h"
19 #include "../w1_int.h"
20 #include "../w1_family.h"
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
24 MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
25 MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));
28 #define W1_F29_RETRIES 3
30 #define W1_F29_REG_LOGIG_STATE 0x88 /* R */
31 #define W1_F29_REG_OUTPUT_LATCH_STATE 0x89 /* R */
32 #define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A /* R */
33 #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */
34 #define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C /* RW */
35 #define W1_F29_REG_CONTROL_AND_STATUS 0x8D /* RW */
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 /* also used to write the control/status reg (0x8D): */
41 #define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC
42 #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3
44 #define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA
46 static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
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);
53 if (!buf)
54 return -EINVAL;
56 mutex_lock(&sl->master->bus_mutex);
57 dev_dbg(&sl->dev, "mutex locked");
59 if (w1_reset_select_slave(sl)) {
60 mutex_unlock(&sl->master->bus_mutex);
61 return -EIO;
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);
70 mutex_unlock(&sl->master->bus_mutex);
71 dev_dbg(&sl->dev, "mutex unlocked");
72 return 1;
75 static 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)
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);
87 static 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)
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);
100 static 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)
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);
113 static 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)
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);
126 static 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)
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);
137 static 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)
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);
147 static 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)
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;
156 if (count != 1 || off != 0)
157 return -EFAULT;
159 dev_dbg(&sl->dev, "locking mutex for write_output");
160 mutex_lock(&sl->master->bus_mutex);
161 dev_dbg(&sl->dev, "mutex locked");
163 if (w1_reset_select_slave(sl))
164 goto error;
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);
172 readBack = w1_read_8(sl->master);
174 if (readBack != W1_F29_SUCCESS_CONFIRM_BYTE) {
175 if (w1_reset_resume_command(sl->master))
176 goto error;
177 /* try again, the slave is ready for a command */
178 continue;
181 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK
182 /* here the master could read another byte which
183 would be the PIO reg (the actual pin logic state)
184 since in this driver we don't know which pins are
185 in and outs, there's no value to read the state and
186 compare. with (*buf) so end this command abruptly: */
187 if (w1_reset_resume_command(sl->master))
188 goto error;
190 /* go read back the output latches */
191 /* (the direct effect of the write above) */
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 /* read the result of the READ_PIO_REGS command */
197 if (w1_read_8(sl->master) == *buf)
198 #endif
200 /* success! */
201 mutex_unlock(&sl->master->bus_mutex);
202 dev_dbg(&sl->dev,
203 "mutex unlocked, retries:%d", retries);
204 return 1;
207 error:
208 mutex_unlock(&sl->master->bus_mutex);
209 dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries);
211 return -EIO;
216 * Writing to the activity file resets the activity latches.
218 static 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)
222 struct w1_slave *sl = kobj_to_w1_slave(kobj);
223 unsigned int retries = W1_F29_RETRIES;
225 if (count != 1 || off != 0)
226 return -EFAULT;
228 mutex_lock(&sl->master->bus_mutex);
230 if (w1_reset_select_slave(sl))
231 goto error;
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;
239 if (w1_reset_resume_command(sl->master))
240 goto error;
243 error:
244 mutex_unlock(&sl->master->bus_mutex);
245 return -EIO;
248 static 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)
252 struct w1_slave *sl = kobj_to_w1_slave(kobj);
253 u8 w1_buf[4];
254 unsigned int retries = W1_F29_RETRIES;
256 if (count != 1 || off != 0)
257 return -EFAULT;
259 mutex_lock(&sl->master->bus_mutex);
261 if (w1_reset_select_slave(sl))
262 goto error;
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;
270 w1_write_block(sl->master, w1_buf, 4);
271 if (w1_reset_resume_command(sl->master))
272 goto error;
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;
278 w1_write_block(sl->master, w1_buf, 3);
279 if (w1_read_8(sl->master) == *buf) {
280 /* success! */
281 mutex_unlock(&sl->master->bus_mutex);
282 return 1;
285 error:
286 mutex_unlock(&sl->master->bus_mutex);
288 return -EIO;
292 * This is a special sequence we must do to ensure the P0 output is not stuck
293 * in test mode. This is described in rev 2 of the ds2408's datasheet
294 * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under
295 * "APPLICATION INFORMATION/Power-up timing".
297 static int w1_f29_disable_test_mode(struct w1_slave *sl)
299 int res;
300 u8 magic[10] = {0x96, };
301 u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
303 memcpy(&magic[1], &rn, 8);
304 magic[9] = 0x3C;
306 mutex_lock(&sl->master->bus_mutex);
308 res = w1_reset_bus(sl->master);
309 if (res)
310 goto out;
311 w1_write_block(sl->master, magic, ARRAY_SIZE(magic));
313 res = w1_reset_bus(sl->master);
314 out:
315 mutex_unlock(&sl->master->bus_mutex);
316 return res;
319 static BIN_ATTR_RO(state, 1);
320 static BIN_ATTR_RW(output, 1);
321 static BIN_ATTR_RW(activity, 1);
322 static BIN_ATTR_RO(cond_search_mask, 1);
323 static BIN_ATTR_RO(cond_search_polarity, 1);
324 static BIN_ATTR_RW(status_control, 1);
326 static 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,
336 static const struct attribute_group w1_f29_group = {
337 .bin_attrs = w1_f29_bin_attrs,
340 static const struct attribute_group *w1_f29_groups[] = {
341 &w1_f29_group,
342 NULL,
345 static struct w1_family_ops w1_f29_fops = {
346 .add_slave = w1_f29_disable_test_mode,
347 .groups = w1_f29_groups,
350 static struct w1_family w1_family_29 = {
351 .fid = W1_FAMILY_DS2408,
352 .fops = &w1_f29_fops,
355 static int __init w1_f29_init(void)
357 return w1_register_family(&w1_family_29);
360 static void __exit w1_f29_exit(void)
362 w1_unregister_family(&w1_family_29);
365 module_init(w1_f29_init);
366 module_exit(w1_f29_exit);