diff options
Diffstat (limited to 'drivers/w1/w1_therm.c')
-rw-r--r-- | drivers/w1/w1_therm.c | 92 |
1 files changed, 82 insertions, 10 deletions
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c index 70310f7a722e..84e8043a4499 100644 --- a/drivers/w1/w1_therm.c +++ b/drivers/w1/w1_therm.c | |||
@@ -53,6 +53,50 @@ static struct w1_family_ops w1_therm_fops = { | |||
53 | .rvalname = "temp1_input", | 53 | .rvalname = "temp1_input", |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static struct w1_family w1_therm_family_DS18S20 = { | ||
57 | .fid = W1_THERM_DS18S20, | ||
58 | .fops = &w1_therm_fops, | ||
59 | }; | ||
60 | |||
61 | static struct w1_family w1_therm_family_DS18B20 = { | ||
62 | .fid = W1_THERM_DS18B20, | ||
63 | .fops = &w1_therm_fops, | ||
64 | }; | ||
65 | static struct w1_family w1_therm_family_DS1822 = { | ||
66 | .fid = W1_THERM_DS1822, | ||
67 | .fops = &w1_therm_fops, | ||
68 | }; | ||
69 | |||
70 | struct w1_therm_family_converter | ||
71 | { | ||
72 | u8 fid; | ||
73 | u8 broken; | ||
74 | u16 reserved; | ||
75 | struct w1_family *f; | ||
76 | int (*convert)(u8 rom[9]); | ||
77 | }; | ||
78 | |||
79 | static inline int w1_DS18B20_convert_temp(u8 rom[9]); | ||
80 | static inline int w1_DS18S20_convert_temp(u8 rom[9]); | ||
81 | |||
82 | static struct w1_therm_family_converter w1_therm_families[] = { | ||
83 | { | ||
84 | .fid = W1_THERM_DS18S20, | ||
85 | .f = &w1_therm_family_DS18S20, | ||
86 | .convert = w1_DS18S20_convert_temp | ||
87 | }, | ||
88 | { | ||
89 | .fid = W1_THERM_DS1822, | ||
90 | .f = &w1_therm_family_DS1822, | ||
91 | .convert = w1_DS18B20_convert_temp | ||
92 | }, | ||
93 | { | ||
94 | .fid = W1_THERM_DS18B20, | ||
95 | .f = &w1_therm_family_DS18B20, | ||
96 | .convert = w1_DS18B20_convert_temp | ||
97 | }, | ||
98 | }; | ||
99 | |||
56 | static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf) | 100 | static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf) |
57 | { | 101 | { |
58 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 102 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); |
@@ -60,9 +104,19 @@ static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *a | |||
60 | return sprintf(buf, "%s\n", sl->name); | 104 | return sprintf(buf, "%s\n", sl->name); |
61 | } | 105 | } |
62 | 106 | ||
63 | static inline int w1_convert_temp(u8 rom[9]) | 107 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) |
108 | { | ||
109 | int t = (rom[1] << 8) | rom[0]; | ||
110 | t /= 16; | ||
111 | return t; | ||
112 | } | ||
113 | |||
114 | static inline int w1_DS18S20_convert_temp(u8 rom[9]) | ||
64 | { | 115 | { |
65 | int t, h; | 116 | int t, h; |
117 | |||
118 | if (!rom[7]) | ||
119 | return 0; | ||
66 | 120 | ||
67 | if (rom[1] == 0) | 121 | if (rom[1] == 0) |
68 | t = ((s32)rom[0] >> 1)*1000; | 122 | t = ((s32)rom[0] >> 1)*1000; |
@@ -77,11 +131,22 @@ static inline int w1_convert_temp(u8 rom[9]) | |||
77 | return t; | 131 | return t; |
78 | } | 132 | } |
79 | 133 | ||
134 | static inline int w1_convert_temp(u8 rom[9], u8 fid) | ||
135 | { | ||
136 | int i; | ||
137 | |||
138 | for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) | ||
139 | if (w1_therm_families[i].fid == fid) | ||
140 | return w1_therm_families[i].convert(rom); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
80 | static ssize_t w1_therm_read_temp(struct device *dev, struct device_attribute *attr, char *buf) | 145 | static ssize_t w1_therm_read_temp(struct device *dev, struct device_attribute *attr, char *buf) |
81 | { | 146 | { |
82 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 147 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); |
83 | 148 | ||
84 | return sprintf(buf, "%d\n", w1_convert_temp(sl->rom)); | 149 | return sprintf(buf, "%d\n", w1_convert_temp(sl->rom, sl->family->fid)); |
85 | } | 150 | } |
86 | 151 | ||
87 | static int w1_therm_check_rom(u8 rom[9]) | 152 | static int w1_therm_check_rom(u8 rom[9]) |
@@ -176,7 +241,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si | |||
176 | for (i = 0; i < 9; ++i) | 241 | for (i = 0; i < 9; ++i) |
177 | count += sprintf(buf + count, "%02x ", sl->rom[i]); | 242 | count += sprintf(buf + count, "%02x ", sl->rom[i]); |
178 | 243 | ||
179 | count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom)); | 244 | count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid)); |
180 | out: | 245 | out: |
181 | up(&dev->mutex); | 246 | up(&dev->mutex); |
182 | out_dec: | 247 | out_dec: |
@@ -186,19 +251,26 @@ out_dec: | |||
186 | return count; | 251 | return count; |
187 | } | 252 | } |
188 | 253 | ||
189 | static struct w1_family w1_therm_family = { | ||
190 | .fid = W1_FAMILY_THERM, | ||
191 | .fops = &w1_therm_fops, | ||
192 | }; | ||
193 | |||
194 | static int __init w1_therm_init(void) | 254 | static int __init w1_therm_init(void) |
195 | { | 255 | { |
196 | return w1_register_family(&w1_therm_family); | 256 | int err, i; |
257 | |||
258 | for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) { | ||
259 | err = w1_register_family(w1_therm_families[i].f); | ||
260 | if (err) | ||
261 | w1_therm_families[i].broken = 1; | ||
262 | } | ||
263 | |||
264 | return 0; | ||
197 | } | 265 | } |
198 | 266 | ||
199 | static void __exit w1_therm_fini(void) | 267 | static void __exit w1_therm_fini(void) |
200 | { | 268 | { |
201 | w1_unregister_family(&w1_therm_family); | 269 | int i; |
270 | |||
271 | for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) | ||
272 | if (!w1_therm_families[i].broken) | ||
273 | w1_unregister_family(w1_therm_families[i].f); | ||
202 | } | 274 | } |
203 | 275 | ||
204 | module_init(w1_therm_init); | 276 | module_init(w1_therm_init); |