aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1/slaves
diff options
context:
space:
mode:
authorMika Laitio <lamikr@pilppa.org>2011-01-12 20:01:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:22 -0500
commit17fecb5582962c2ca5627a51ec9ab0979fb673ef (patch)
tree108d8b25267e91ec6aeb0781bc4f705e8296541f /drivers/w1/slaves
parent496fc1a68a45ae159d26331775411f6fea36d4d3 (diff)
w1: DS2423 counter driver and documentation
This is a 1-wire/w1 DS2423 slave driver for reading the values from all 4 counters available DS2423 devices by using standard w1_slave file. In ds2423 the counters are tied to ram pages 12-15 in and each of those ram-pages. Each of these counter values (and asoociated ram page values) are represented as a own line in w1_slave file. Driver has been tested on mips and x86. usage example: cat /sys/bus/w1/devices/1d-00000009b964/w1_slave 00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2 00 5a 0e 5f 18 00 00 00 00 0b 28 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408882778 00 05 00 00 00 00 00 00 00 8d 39 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff crc=YES c=5 Patch includes also the documentation. [randy.dunlap@oracle.com: fix ds2423 build, needs to select CRC16] Signed-off-by: Mika Laitio <lamikr@pilppa.org> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/w1/slaves')
-rw-r--r--drivers/w1/slaves/Kconfig11
-rw-r--r--drivers/w1/slaves/Makefile1
-rw-r--r--drivers/w1/slaves/w1_ds2423.c166
3 files changed, 178 insertions, 0 deletions
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 1f51366417b9..f0c909625bd1 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -16,6 +16,17 @@ config W1_SLAVE_SMEM
16 Say Y here if you want to connect 1-wire 16 Say Y here if you want to connect 1-wire
17 simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. 17 simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
18 18
19config W1_SLAVE_DS2423
20 tristate "Counter 1-wire device (DS2423)"
21 select CRC16
22 help
23 If you enable this you can read the counter values available
24 in the DS2423 chipset from the w1_slave file under the
25 sys file system.
26
27 Say Y here if you want to use a 1-wire
28 counter family device (DS2423).
29
19config W1_SLAVE_DS2431 30config W1_SLAVE_DS2431
20 tristate "1kb EEPROM family support (DS2431)" 31 tristate "1kb EEPROM family support (DS2431)"
21 help 32 help
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index f1f51f19b129..3c76350a24f7 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -4,6 +4,7 @@
4 4
5obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o 5obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o
6obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o 6obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o
7obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o
7obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o 8obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o
8obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o 9obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
9obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o 10obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c
new file mode 100644
index 000000000000..7a7dbe5026f1
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2423.c
@@ -0,0 +1,166 @@
1/*
2 * w1_ds2423.c
3 *
4 * Copyright (c) 2010 Mika Laitio <lamikr@pilppa.org>
5 *
6 * This driver will read and write the value of 4 counters to w1_slave file in
7 * sys filesystem.
8 * Inspired by the w1_therm and w1_ds2431 drivers.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the therms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/device.h>
29#include <linux/types.h>
30#include <linux/delay.h>
31#include <linux/crc16.h>
32
33#include "../w1.h"
34#include "../w1_int.h"
35#include "../w1_family.h"
36
37#define CRC16_VALID 0xb001
38#define CRC16_INIT 0
39
40#define COUNTER_COUNT 4
41#define READ_BYTE_COUNT 42
42
43static ssize_t w1_counter_read(struct device *device,
44 struct device_attribute *attr, char *buf);
45
46static struct device_attribute w1_counter_attr =
47 __ATTR(w1_slave, S_IRUGO, w1_counter_read, NULL);
48
49static ssize_t w1_counter_read(struct device *device,
50 struct device_attribute *attr, char *out_buf)
51{
52 struct w1_slave *sl = dev_to_w1_slave(device);
53 struct w1_master *dev = sl->master;
54 u8 rbuf[COUNTER_COUNT * READ_BYTE_COUNT];
55 u8 wrbuf[3];
56 int rom_addr;
57 int read_byte_count;
58 int result;
59 ssize_t c;
60 int ii;
61 int p;
62 int crc;
63
64 c = PAGE_SIZE;
65 rom_addr = (12 << 5) + 31;
66 wrbuf[0] = 0xA5;
67 wrbuf[1] = rom_addr & 0xFF;
68 wrbuf[2] = rom_addr >> 8;
69 mutex_lock(&dev->mutex);
70 if (!w1_reset_select_slave(sl)) {
71 w1_write_block(dev, wrbuf, 3);
72 read_byte_count = 0;
73 for (p = 0; p < 4; p++) {
74 /*
75 * 1 byte for first bytes in ram page read
76 * 4 bytes for counter
77 * 4 bytes for zero bits
78 * 2 bytes for crc
79 * 31 remaining bytes from the ram page
80 */
81 read_byte_count += w1_read_block(dev,
82 rbuf + (p * READ_BYTE_COUNT), READ_BYTE_COUNT);
83 for (ii = 0; ii < READ_BYTE_COUNT; ++ii)
84 c -= snprintf(out_buf + PAGE_SIZE - c,
85 c, "%02x ",
86 rbuf[(p * READ_BYTE_COUNT) + ii]);
87 if (read_byte_count != (p + 1) * READ_BYTE_COUNT) {
88 dev_warn(device,
89 "w1_counter_read() returned %u bytes "
90 "instead of %d bytes wanted.\n",
91 read_byte_count,
92 READ_BYTE_COUNT);
93 c -= snprintf(out_buf + PAGE_SIZE - c,
94 c, "crc=NO\n");
95 } else {
96 if (p == 0) {
97 crc = crc16(CRC16_INIT, wrbuf, 3);
98 crc = crc16(crc, rbuf, 11);
99 } else {
100 /*
101 * DS2423 calculates crc from all bytes
102 * read after the previous crc bytes.
103 */
104 crc = crc16(CRC16_INIT,
105 (rbuf + 11) +
106 ((p - 1) * READ_BYTE_COUNT),
107 READ_BYTE_COUNT);
108 }
109 if (crc == CRC16_VALID) {
110 result = 0;
111 for (ii = 4; ii > 0; ii--) {
112 result <<= 8;
113 result |= rbuf[(p *
114 READ_BYTE_COUNT) + ii];
115 }
116 c -= snprintf(out_buf + PAGE_SIZE - c,
117 c, "crc=YES c=%d\n", result);
118 } else {
119 c -= snprintf(out_buf + PAGE_SIZE - c,
120 c, "crc=NO\n");
121 }
122 }
123 }
124 } else {
125 c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error");
126 }
127 mutex_unlock(&dev->mutex);
128 return PAGE_SIZE - c;
129}
130
131static int w1_f1d_add_slave(struct w1_slave *sl)
132{
133 return device_create_file(&sl->dev, &w1_counter_attr);
134}
135
136static void w1_f1d_remove_slave(struct w1_slave *sl)
137{
138 device_remove_file(&sl->dev, &w1_counter_attr);
139}
140
141static struct w1_family_ops w1_f1d_fops = {
142 .add_slave = w1_f1d_add_slave,
143 .remove_slave = w1_f1d_remove_slave,
144};
145
146static struct w1_family w1_family_1d = {
147 .fid = W1_COUNTER_DS2423,
148 .fops = &w1_f1d_fops,
149};
150
151static int __init w1_f1d_init(void)
152{
153 return w1_register_family(&w1_family_1d);
154}
155
156static void __exit w1_f1d_exit(void)
157{
158 w1_unregister_family(&w1_family_1d);
159}
160
161module_init(w1_f1d_init);
162module_exit(w1_f1d_exit);
163
164MODULE_LICENSE("GPL");
165MODULE_AUTHOR("Mika Laitio <lamikr@pilppa.org>");
166MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram");