ARC: [plat-hsdk]: unify memory apertures configuration
[linux-2.6-microblaze.git] / drivers / w1 / slaves / w1_ds2408.c
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
18 #include <linux/w1.h>
19
20 #define W1_FAMILY_DS2408        0x29
21
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
40 static 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
50         mutex_lock(&sl->master->bus_mutex);
51         dev_dbg(&sl->dev, "mutex locked");
52
53         if (w1_reset_select_slave(sl)) {
54                 mutex_unlock(&sl->master->bus_mutex);
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
64         mutex_unlock(&sl->master->bus_mutex);
65         dev_dbg(&sl->dev, "mutex unlocked");
66         return 1;
67 }
68
69 static 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)
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
81 static 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)
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
94 static 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)
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
107 static 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)
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
120 static 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)
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
131 static 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)
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
141 #ifdef CONFIG_W1_SLAVE_DS2408_READBACK
142 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
143 {
144         u8 w1_buf[3];
145
146         if (w1_reset_resume_command(sl->master))
147                 return false;
148
149         w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
150         w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE;
151         w1_buf[2] = 0;
152
153         w1_write_block(sl->master, w1_buf, 3);
154
155         return (w1_read_8(sl->master) == expected);
156 }
157 #else
158 static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
159 {
160         return true;
161 }
162 #endif
163
164 static ssize_t output_write(struct file *filp, struct kobject *kobj,
165                             struct bin_attribute *bin_attr, char *buf,
166                             loff_t off, size_t count)
167 {
168         struct w1_slave *sl = kobj_to_w1_slave(kobj);
169         u8 w1_buf[3];
170         unsigned int retries = W1_F29_RETRIES;
171         ssize_t bytes_written = -EIO;
172
173         if (count != 1 || off != 0)
174                 return -EFAULT;
175
176         dev_dbg(&sl->dev, "locking mutex for write_output");
177         mutex_lock(&sl->master->bus_mutex);
178         dev_dbg(&sl->dev, "mutex locked");
179
180         if (w1_reset_select_slave(sl))
181                 goto out;
182
183         do {
184                 w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE;
185                 w1_buf[1] = *buf;
186                 w1_buf[2] = ~(*buf);
187
188                 w1_write_block(sl->master, w1_buf, 3);
189
190                 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE &&
191                     optional_read_back_valid(sl, *buf)) {
192                         bytes_written = 1;
193                         goto out;
194                 }
195
196                 if (w1_reset_resume_command(sl->master))
197                         goto out; /* unrecoverable error */
198                 /* try again, the slave is ready for a command */
199         } while (--retries);
200
201 out:
202         mutex_unlock(&sl->master->bus_mutex);
203
204         dev_dbg(&sl->dev, "%s, mutex unlocked retries:%d\n",
205                 (bytes_written > 0) ? "succeeded" : "error", retries);
206
207         return bytes_written;
208 }
209
210
211 /**
212  * Writing to the activity file resets the activity latches.
213  */
214 static ssize_t activity_write(struct file *filp, struct kobject *kobj,
215                               struct bin_attribute *bin_attr, char *buf,
216                               loff_t off, size_t count)
217 {
218         struct w1_slave *sl = kobj_to_w1_slave(kobj);
219         unsigned int retries = W1_F29_RETRIES;
220
221         if (count != 1 || off != 0)
222                 return -EFAULT;
223
224         mutex_lock(&sl->master->bus_mutex);
225
226         if (w1_reset_select_slave(sl))
227                 goto error;
228
229         while (retries--) {
230                 w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES);
231                 if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) {
232                         mutex_unlock(&sl->master->bus_mutex);
233                         return 1;
234                 }
235                 if (w1_reset_resume_command(sl->master))
236                         goto error;
237         }
238
239 error:
240         mutex_unlock(&sl->master->bus_mutex);
241         return -EIO;
242 }
243
244 static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
245                                     struct bin_attribute *bin_attr, char *buf,
246                                     loff_t off, size_t count)
247 {
248         struct w1_slave *sl = kobj_to_w1_slave(kobj);
249         u8 w1_buf[4];
250         unsigned int retries = W1_F29_RETRIES;
251
252         if (count != 1 || off != 0)
253                 return -EFAULT;
254
255         mutex_lock(&sl->master->bus_mutex);
256
257         if (w1_reset_select_slave(sl))
258                 goto error;
259
260         while (retries--) {
261                 w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG;
262                 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
263                 w1_buf[2] = 0;
264                 w1_buf[3] = *buf;
265
266                 w1_write_block(sl->master, w1_buf, 4);
267                 if (w1_reset_resume_command(sl->master))
268                         goto error;
269
270                 w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS;
271                 w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS;
272                 w1_buf[2] = 0;
273
274                 w1_write_block(sl->master, w1_buf, 3);
275                 if (w1_read_8(sl->master) == *buf) {
276                         /* success! */
277                         mutex_unlock(&sl->master->bus_mutex);
278                         return 1;
279                 }
280         }
281 error:
282         mutex_unlock(&sl->master->bus_mutex);
283
284         return -EIO;
285 }
286
287 /*
288  * This is a special sequence we must do to ensure the P0 output is not stuck
289  * in test mode. This is described in rev 2 of the ds2408's datasheet
290  * (http://datasheets.maximintegrated.com/en/ds/DS2408.pdf) under
291  * "APPLICATION INFORMATION/Power-up timing".
292  */
293 static int w1_f29_disable_test_mode(struct w1_slave *sl)
294 {
295         int res;
296         u8 magic[10] = {0x96, };
297         u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
298
299         memcpy(&magic[1], &rn, 8);
300         magic[9] = 0x3C;
301
302         mutex_lock(&sl->master->bus_mutex);
303
304         res = w1_reset_bus(sl->master);
305         if (res)
306                 goto out;
307         w1_write_block(sl->master, magic, ARRAY_SIZE(magic));
308
309         res = w1_reset_bus(sl->master);
310 out:
311         mutex_unlock(&sl->master->bus_mutex);
312         return res;
313 }
314
315 static BIN_ATTR_RO(state, 1);
316 static BIN_ATTR_RW(output, 1);
317 static BIN_ATTR_RW(activity, 1);
318 static BIN_ATTR_RO(cond_search_mask, 1);
319 static BIN_ATTR_RO(cond_search_polarity, 1);
320 static BIN_ATTR_RW(status_control, 1);
321
322 static struct bin_attribute *w1_f29_bin_attrs[] = {
323         &bin_attr_state,
324         &bin_attr_output,
325         &bin_attr_activity,
326         &bin_attr_cond_search_mask,
327         &bin_attr_cond_search_polarity,
328         &bin_attr_status_control,
329         NULL,
330 };
331
332 static const struct attribute_group w1_f29_group = {
333         .bin_attrs = w1_f29_bin_attrs,
334 };
335
336 static const struct attribute_group *w1_f29_groups[] = {
337         &w1_f29_group,
338         NULL,
339 };
340
341 static struct w1_family_ops w1_f29_fops = {
342         .add_slave      = w1_f29_disable_test_mode,
343         .groups         = w1_f29_groups,
344 };
345
346 static struct w1_family w1_family_29 = {
347         .fid = W1_FAMILY_DS2408,
348         .fops = &w1_f29_fops,
349 };
350 module_w1_family(w1_family_29);
351
352 MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>");
353 MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO");
354 MODULE_LICENSE("GPL");
355 MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408));