blob: 98117db595bbe1ed97088e9edd2713a3a6cc06eb [file] [log] [blame]
Markus Frankefbf7f7b2012-05-26 00:45:12 +02001/*
2 * w1_ds28e04.c - w1 family 1C (DS28E04) driver
3 *
4 * Copyright (c) 2012 Markus Franke <franke.m@sebakmt.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#include <linux/crc16.h>
18#include <linux/uaccess.h>
19
20#define CRC16_INIT 0
21#define CRC16_VALID 0xb001
22
23#include "../w1.h"
24#include "../w1_int.h"
25#include "../w1_family.h"
26
27MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Markus Franke <franke.m@sebakmt.com>, <franm@hrz.tu-chemnitz.de>");
29MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO");
30
31/* Allow the strong pullup to be disabled, but default to enabled.
32 * If it was disabled a parasite powered device might not get the required
33 * current to copy the data from the scratchpad to EEPROM. If it is enabled
34 * parasite powered devices have a better chance of getting the current
35 * required.
36 */
37static int w1_strong_pullup = 1;
38module_param_named(strong_pullup, w1_strong_pullup, int, 0);
39
40/* enable/disable CRC checking on DS28E04-100 memory accesses */
41static char w1_enable_crccheck = 1;
42
43#define W1_EEPROM_SIZE 512
44#define W1_PAGE_COUNT 16
45#define W1_PAGE_SIZE 32
46#define W1_PAGE_BITS 5
47#define W1_PAGE_MASK 0x1F
48
49#define W1_F1C_READ_EEPROM 0xF0
50#define W1_F1C_WRITE_SCRATCH 0x0F
51#define W1_F1C_READ_SCRATCH 0xAA
52#define W1_F1C_COPY_SCRATCH 0x55
53#define W1_F1C_ACCESS_WRITE 0x5A
54
55#define W1_1C_REG_LOGIC_STATE 0x220
56
57struct w1_f1C_data {
58 u8 memory[W1_EEPROM_SIZE];
59 u32 validcrc;
60};
61
62/**
63 * Check the file size bounds and adjusts count as needed.
64 * This would not be needed if the file size didn't reset to 0 after a write.
65 */
66static inline size_t w1_f1C_fix_count(loff_t off, size_t count, size_t size)
67{
68 if (off > size)
69 return 0;
70
71 if ((off + count) > size)
72 return size - off;
73
74 return count;
75}
76
77static int w1_f1C_refresh_block(struct w1_slave *sl, struct w1_f1C_data *data,
78 int block)
79{
80 u8 wrbuf[3];
81 int off = block * W1_PAGE_SIZE;
82
83 if (data->validcrc & (1 << block))
84 return 0;
85
86 if (w1_reset_select_slave(sl)) {
87 data->validcrc = 0;
88 return -EIO;
89 }
90
91 wrbuf[0] = W1_F1C_READ_EEPROM;
92 wrbuf[1] = off & 0xff;
93 wrbuf[2] = off >> 8;
94 w1_write_block(sl->master, wrbuf, 3);
95 w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
96
97 /* cache the block if the CRC is valid */
98 if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
99 data->validcrc |= (1 << block);
100
101 return 0;
102}
103
104static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data)
105{
106 u8 wrbuf[3];
107
108 /* read directly from the EEPROM */
109 if (w1_reset_select_slave(sl))
110 return -EIO;
111
112 wrbuf[0] = W1_F1C_READ_EEPROM;
113 wrbuf[1] = addr & 0xff;
114 wrbuf[2] = addr >> 8;
115
116 w1_write_block(sl->master, wrbuf, sizeof(wrbuf));
117 return w1_read_block(sl->master, data, len);
118}
119
120static ssize_t w1_f1C_read_bin(struct file *filp, struct kobject *kobj,
121 struct bin_attribute *bin_attr,
122 char *buf, loff_t off, size_t count)
123{
124 struct w1_slave *sl = kobj_to_w1_slave(kobj);
125 struct w1_f1C_data *data = sl->family_data;
126 int i, min_page, max_page;
127
128 count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE);
129 if (count == 0)
130 return 0;
131
132 mutex_lock(&sl->master->mutex);
133
134 if (w1_enable_crccheck) {
135 min_page = (off >> W1_PAGE_BITS);
136 max_page = (off + count - 1) >> W1_PAGE_BITS;
137 for (i = min_page; i <= max_page; i++) {
138 if (w1_f1C_refresh_block(sl, data, i)) {
139 count = -EIO;
140 goto out_up;
141 }
142 }
143 memcpy(buf, &data->memory[off], count);
144 } else {
145 count = w1_f1C_read(sl, off, count, buf);
146 }
147
148out_up:
149 mutex_unlock(&sl->master->mutex);
150
151 return count;
152}
153
154/**
155 * Writes to the scratchpad and reads it back for verification.
156 * Then copies the scratchpad to EEPROM.
157 * The data must be on one page.
158 * The master must be locked.
159 *
160 * @param sl The slave structure
161 * @param addr Address for the write
162 * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
163 * @param data The data to write
164 * @return 0=Success -1=failure
165 */
166static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data)
167{
168 u8 wrbuf[4];
169 u8 rdbuf[W1_PAGE_SIZE + 3];
170 u8 es = (addr + len - 1) & 0x1f;
171 unsigned int tm = 10;
172 int i;
173 struct w1_f1C_data *f1C = sl->family_data;
174
175 /* Write the data to the scratchpad */
176 if (w1_reset_select_slave(sl))
177 return -1;
178
179 wrbuf[0] = W1_F1C_WRITE_SCRATCH;
180 wrbuf[1] = addr & 0xff;
181 wrbuf[2] = addr >> 8;
182
183 w1_write_block(sl->master, wrbuf, 3);
184 w1_write_block(sl->master, data, len);
185
186 /* Read the scratchpad and verify */
187 if (w1_reset_select_slave(sl))
188 return -1;
189
190 w1_write_8(sl->master, W1_F1C_READ_SCRATCH);
191 w1_read_block(sl->master, rdbuf, len + 3);
192
193 /* Compare what was read against the data written */
194 if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
195 (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0))
196 return -1;
197
198 /* Copy the scratchpad to EEPROM */
199 if (w1_reset_select_slave(sl))
200 return -1;
201
202 wrbuf[0] = W1_F1C_COPY_SCRATCH;
203 wrbuf[3] = es;
204
205 for (i = 0; i < sizeof(wrbuf); ++i) {
206 /* issue 10ms strong pullup (or delay) on the last byte
207 for writing the data from the scratchpad to EEPROM */
208 if (w1_strong_pullup && i == sizeof(wrbuf)-1)
209 w1_next_pullup(sl->master, tm);
210
211 w1_write_8(sl->master, wrbuf[i]);
212 }
213
214 if (!w1_strong_pullup)
215 msleep(tm);
216
217 if (w1_enable_crccheck) {
218 /* invalidate cached data */
219 f1C->validcrc &= ~(1 << (addr >> W1_PAGE_BITS));
220 }
221
222 /* Reset the bus to wake up the EEPROM (this may not be needed) */
223 w1_reset_bus(sl->master);
224
225 return 0;
226}
227
228static ssize_t w1_f1C_write_bin(struct file *filp, struct kobject *kobj,
229 struct bin_attribute *bin_attr,
230 char *buf, loff_t off, size_t count)
231
232{
233 struct w1_slave *sl = kobj_to_w1_slave(kobj);
234 int addr, len, idx;
235
236 count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE);
237 if (count == 0)
238 return 0;
239
240 if (w1_enable_crccheck) {
241 /* can only write full blocks in cached mode */
242 if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
243 dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
244 (int)off, count);
245 return -EINVAL;
246 }
247
248 /* make sure the block CRCs are valid */
249 for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
250 if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE)
251 != CRC16_VALID) {
252 dev_err(&sl->dev, "bad CRC at offset %d\n",
253 (int)off);
254 return -EINVAL;
255 }
256 }
257 }
258
259 mutex_lock(&sl->master->mutex);
260
261 /* Can only write data to one page at a time */
262 idx = 0;
263 while (idx < count) {
264 addr = off + idx;
265 len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
266 if (len > (count - idx))
267 len = count - idx;
268
269 if (w1_f1C_write(sl, addr, len, &buf[idx]) < 0) {
270 count = -EIO;
271 goto out_up;
272 }
273 idx += len;
274 }
275
276out_up:
277 mutex_unlock(&sl->master->mutex);
278
279 return count;
280}
281
282static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj,
283 struct bin_attribute *bin_attr,
284 char *buf, loff_t off, size_t count)
285
286{
287 struct w1_slave *sl = kobj_to_w1_slave(kobj);
288 int ret;
289
290 /* check arguments */
291 if (off != 0 || count != 1 || buf == NULL)
292 return -EINVAL;
293
294 mutex_lock(&sl->master->mutex);
295 ret = w1_f1C_read(sl, W1_1C_REG_LOGIC_STATE, count, buf);
296 mutex_unlock(&sl->master->mutex);
297
298 return ret;
299}
300
301static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj,
302 struct bin_attribute *bin_attr,
303 char *buf, loff_t off, size_t count)
304
305{
306 struct w1_slave *sl = kobj_to_w1_slave(kobj);
307 u8 wrbuf[3];
308 u8 ack;
309
310 /* check arguments */
311 if (off != 0 || count != 1 || buf == NULL)
312 return -EINVAL;
313
314 mutex_lock(&sl->master->mutex);
315
316 /* Write the PIO data */
317 if (w1_reset_select_slave(sl)) {
318 mutex_unlock(&sl->master->mutex);
319 return -1;
320 }
321
322 /* set bit 7..2 to value '1' */
323 *buf = *buf | 0xFC;
324
325 wrbuf[0] = W1_F1C_ACCESS_WRITE;
326 wrbuf[1] = *buf;
327 wrbuf[2] = ~(*buf);
328 w1_write_block(sl->master, wrbuf, 3);
329
330 w1_read_block(sl->master, &ack, sizeof(ack));
331
332 mutex_unlock(&sl->master->mutex);
333
334 /* check for acknowledgement */
335 if (ack != 0xAA)
336 return -EIO;
337
338 return count;
339}
340
341static ssize_t w1_f1C_show_crccheck(struct device *dev,
342 struct device_attribute *attr, char *buf)
343{
344 if (put_user(w1_enable_crccheck + 0x30, buf))
345 return -EFAULT;
346
347 return sizeof(w1_enable_crccheck);
348}
349
350static ssize_t w1_f1C_store_crccheck(struct device *dev,
351 struct device_attribute *attr,
352 const char *buf, size_t count)
353{
354 char val;
355
356 if (count != 1 || !buf)
357 return -EINVAL;
358
359 if (get_user(val, buf))
360 return -EFAULT;
361
362 /* convert to decimal */
363 val = val - 0x30;
364 if (val != 0 && val != 1)
365 return -EINVAL;
366
367 /* set the new value */
368 w1_enable_crccheck = val;
369
370 return sizeof(w1_enable_crccheck);
371}
372
373#define NB_SYSFS_BIN_FILES 2
374static struct bin_attribute w1_f1C_bin_attr[NB_SYSFS_BIN_FILES] = {
375 {
376 .attr = {
377 .name = "eeprom",
378 .mode = S_IRUGO | S_IWUSR,
379 },
380 .size = W1_EEPROM_SIZE,
381 .read = w1_f1C_read_bin,
382 .write = w1_f1C_write_bin,
383 },
384 {
385 .attr = {
386 .name = "pio",
387 .mode = S_IRUGO | S_IWUSR,
388 },
389 .size = 1,
390 .read = w1_f1C_read_pio,
391 .write = w1_f1C_write_pio,
392 }
393};
394
395static DEVICE_ATTR(crccheck, S_IWUSR | S_IRUGO,
396 w1_f1C_show_crccheck, w1_f1C_store_crccheck);
397
398static int w1_f1C_add_slave(struct w1_slave *sl)
399{
400 int err = 0;
401 int i;
402 struct w1_f1C_data *data = NULL;
403
404 if (w1_enable_crccheck) {
405 data = kzalloc(sizeof(struct w1_f1C_data), GFP_KERNEL);
406 if (!data)
407 return -ENOMEM;
408 sl->family_data = data;
409 }
410
411 /* create binary sysfs attributes */
412 for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
413 err = sysfs_create_bin_file(
414 &sl->dev.kobj, &(w1_f1C_bin_attr[i]));
415
416 if (!err) {
417 /* create device attributes */
418 err = device_create_file(&sl->dev, &dev_attr_crccheck);
419 }
420
421 if (err) {
422 /* remove binary sysfs attributes */
423 for (i = 0; i < NB_SYSFS_BIN_FILES; ++i)
424 sysfs_remove_bin_file(
425 &sl->dev.kobj, &(w1_f1C_bin_attr[i]));
426
427 kfree(data);
428 }
429
430 return err;
431}
432
433static void w1_f1C_remove_slave(struct w1_slave *sl)
434{
435 int i;
436
437 kfree(sl->family_data);
438 sl->family_data = NULL;
439
440 /* remove device attributes */
441 device_remove_file(&sl->dev, &dev_attr_crccheck);
442
443 /* remove binary sysfs attributes */
444 for (i = 0; i < NB_SYSFS_BIN_FILES; ++i)
445 sysfs_remove_bin_file(&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
446}
447
448static struct w1_family_ops w1_f1C_fops = {
449 .add_slave = w1_f1C_add_slave,
450 .remove_slave = w1_f1C_remove_slave,
451};
452
453static struct w1_family w1_family_1C = {
454 .fid = W1_FAMILY_DS28E04,
455 .fops = &w1_f1C_fops,
456};
457
458static int __init w1_f1C_init(void)
459{
460 return w1_register_family(&w1_family_1C);
461}
462
463static void __exit w1_f1C_fini(void)
464{
465 w1_unregister_family(&w1_family_1C);
466}
467
468module_init(w1_f1C_init);
469module_exit(w1_f1C_fini);