diff options
-rw-r--r-- | Documentation/w1/slaves/00-INDEX | 2 | ||||
-rw-r--r-- | Documentation/w1/slaves/w1_ds2423 | 47 | ||||
-rw-r--r-- | drivers/w1/slaves/Kconfig | 11 | ||||
-rw-r--r-- | drivers/w1/slaves/Makefile | 1 | ||||
-rw-r--r-- | drivers/w1/slaves/w1_ds2423.c | 166 | ||||
-rw-r--r-- | drivers/w1/w1_family.h | 1 |
6 files changed, 228 insertions, 0 deletions
diff --git a/Documentation/w1/slaves/00-INDEX b/Documentation/w1/slaves/00-INDEX index f8101d6b07b7..75613c9ac4db 100644 --- a/Documentation/w1/slaves/00-INDEX +++ b/Documentation/w1/slaves/00-INDEX | |||
@@ -2,3 +2,5 @@ | |||
2 | - This file | 2 | - This file |
3 | w1_therm | 3 | w1_therm |
4 | - The Maxim/Dallas Semiconductor ds18*20 temperature sensor. | 4 | - The Maxim/Dallas Semiconductor ds18*20 temperature sensor. |
5 | w1_ds2423 | ||
6 | - The Maxim/Dallas Semiconductor ds2423 counter device. | ||
diff --git a/Documentation/w1/slaves/w1_ds2423 b/Documentation/w1/slaves/w1_ds2423 new file mode 100644 index 000000000000..90a65d23cf59 --- /dev/null +++ b/Documentation/w1/slaves/w1_ds2423 | |||
@@ -0,0 +1,47 @@ | |||
1 | Kernel driver w1_ds2423 | ||
2 | ======================= | ||
3 | |||
4 | Supported chips: | ||
5 | * Maxim DS2423 based counter devices. | ||
6 | |||
7 | supported family codes: | ||
8 | W1_THERM_DS2423 0x1D | ||
9 | |||
10 | Author: Mika Laitio <lamikr@pilppa.org> | ||
11 | |||
12 | Description | ||
13 | ----------- | ||
14 | |||
15 | Support is provided through the sysfs w1_slave file. Each opening and | ||
16 | read sequence of w1_slave file initiates the read of counters and ram | ||
17 | available in DS2423 pages 12 - 15. | ||
18 | |||
19 | Result of each page is provided as an ASCII output where each counter | ||
20 | value and associated ram buffer is outpputed to own line. | ||
21 | |||
22 | Each lines will contain the values of 42 bytes read from the counter and | ||
23 | memory page along the crc=YES or NO for indicating whether the read operation | ||
24 | was successfull and CRC matched. | ||
25 | If the operation was successfull, there is also in the end of each line | ||
26 | a counter value expressed as an integer after c= | ||
27 | |||
28 | Meaning of 42 bytes represented is following: | ||
29 | - 1 byte from ram page | ||
30 | - 4 bytes for the counter value | ||
31 | - 4 zero bytes | ||
32 | - 2 bytes for crc16 which was calculated from the data read since the previous crc bytes | ||
33 | - 31 remaining bytes from the ram page | ||
34 | - crc=YES/NO indicating whether read was ok and crc matched | ||
35 | - c=<int> current counter value | ||
36 | |||
37 | example from the successfull read: | ||
38 | 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 | ||
39 | 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 | ||
40 | 00 29 c6 5d 18 00 00 00 00 04 37 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=408798761 | ||
41 | 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 | ||
42 | |||
43 | example from the read with crc errors: | ||
44 | 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 | ||
45 | 00 02 00 00 22 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=NO | ||
46 | 00 e1 61 5d 19 00 00 00 00 df 0b 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=NO | ||
47 | 00 05 00 00 20 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=NO | ||
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 | ||
19 | config 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 | |||
19 | config W1_SLAVE_DS2431 | 30 | config 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 | ||
5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o | 5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o |
6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o | 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o |
7 | obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o | ||
7 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o | 8 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o |
8 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 9 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
9 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 10 | obj-$(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 | |||
43 | static ssize_t w1_counter_read(struct device *device, | ||
44 | struct device_attribute *attr, char *buf); | ||
45 | |||
46 | static struct device_attribute w1_counter_attr = | ||
47 | __ATTR(w1_slave, S_IRUGO, w1_counter_read, NULL); | ||
48 | |||
49 | static 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 | |||
131 | static int w1_f1d_add_slave(struct w1_slave *sl) | ||
132 | { | ||
133 | return device_create_file(&sl->dev, &w1_counter_attr); | ||
134 | } | ||
135 | |||
136 | static void w1_f1d_remove_slave(struct w1_slave *sl) | ||
137 | { | ||
138 | device_remove_file(&sl->dev, &w1_counter_attr); | ||
139 | } | ||
140 | |||
141 | static struct w1_family_ops w1_f1d_fops = { | ||
142 | .add_slave = w1_f1d_add_slave, | ||
143 | .remove_slave = w1_f1d_remove_slave, | ||
144 | }; | ||
145 | |||
146 | static struct w1_family w1_family_1d = { | ||
147 | .fid = W1_COUNTER_DS2423, | ||
148 | .fops = &w1_f1d_fops, | ||
149 | }; | ||
150 | |||
151 | static int __init w1_f1d_init(void) | ||
152 | { | ||
153 | return w1_register_family(&w1_family_1d); | ||
154 | } | ||
155 | |||
156 | static void __exit w1_f1d_exit(void) | ||
157 | { | ||
158 | w1_unregister_family(&w1_family_1d); | ||
159 | } | ||
160 | |||
161 | module_init(w1_f1d_init); | ||
162 | module_exit(w1_f1d_exit); | ||
163 | |||
164 | MODULE_LICENSE("GPL"); | ||
165 | MODULE_AUTHOR("Mika Laitio <lamikr@pilppa.org>"); | ||
166 | MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram"); | ||
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 3ca1b9298f21..f3b636d7cafe 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define W1_FAMILY_SMEM_01 0x01 | 30 | #define W1_FAMILY_SMEM_01 0x01 |
31 | #define W1_FAMILY_SMEM_81 0x81 | 31 | #define W1_FAMILY_SMEM_81 0x81 |
32 | #define W1_THERM_DS18S20 0x10 | 32 | #define W1_THERM_DS18S20 0x10 |
33 | #define W1_COUNTER_DS2423 0x1D | ||
33 | #define W1_THERM_DS1822 0x22 | 34 | #define W1_THERM_DS1822 0x22 |
34 | #define W1_EEPROM_DS2433 0x23 | 35 | #define W1_EEPROM_DS2433 0x23 |
35 | #define W1_THERM_DS18B20 0x28 | 36 | #define W1_THERM_DS18B20 0x28 |