Commit d01b847c5cd070895c4ba178c85cd068a95cf7cd
Committed by
Wolfgang Denk
1 parent
5a910c224b
Exists in
master
and in
54 other branches
LM75 bug fix for negative temperatures
When the LM75 temperature sensor measures a temperature below 0 C, the current driver does not perform sign extension, so the result returned is 256 C too high. This patch fixes the problem. Signed-off-by: Larry Johnson <lrj@acm.org>
Showing 1 changed file with 7 additions and 1 deletions Inline Diff
drivers/hwmon/lm75.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2001 | 2 | * (C) Copyright 2001 |
3 | * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net | 3 | * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net |
4 | * | 4 | * |
5 | * See file CREDITS for list of people who contributed to this | 5 | * See file CREDITS for list of people who contributed to this |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of | 10 | * published by the Free Software Foundation; either version 2 of |
11 | * the License, or (at your option) any later version. | 11 | * the License, or (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA | 21 | * MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * On Semiconductor's LM75 Temperature Sensor | 25 | * On Semiconductor's LM75 Temperature Sensor |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <common.h> | 28 | #include <common.h> |
29 | 29 | ||
30 | #ifdef CONFIG_DTT_LM75 | 30 | #ifdef CONFIG_DTT_LM75 |
31 | #if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \ | 31 | #if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \ |
32 | (CFG_EEPROM_PAGE_WRITE_BITS < 1) | 32 | (CFG_EEPROM_PAGE_WRITE_BITS < 1) |
33 | # error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_LM75" | 33 | # error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_LM75" |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #include <i2c.h> | 36 | #include <i2c.h> |
37 | #include <dtt.h> | 37 | #include <dtt.h> |
38 | 38 | ||
39 | 39 | ||
40 | /* | 40 | /* |
41 | * Device code | 41 | * Device code |
42 | */ | 42 | */ |
43 | #define DTT_I2C_DEV_CODE 0x48 /* ON Semi's LM75 device */ | 43 | #define DTT_I2C_DEV_CODE 0x48 /* ON Semi's LM75 device */ |
44 | 44 | ||
45 | int dtt_read(int sensor, int reg) | 45 | int dtt_read(int sensor, int reg) |
46 | { | 46 | { |
47 | int dlen; | 47 | int dlen; |
48 | uchar data[2]; | 48 | uchar data[2]; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Validate 'reg' param | 51 | * Validate 'reg' param |
52 | */ | 52 | */ |
53 | if((reg < 0) || (reg > 3)) | 53 | if((reg < 0) || (reg > 3)) |
54 | return -1; | 54 | return -1; |
55 | 55 | ||
56 | /* | 56 | /* |
57 | * Calculate sensor address and register. | 57 | * Calculate sensor address and register. |
58 | */ | 58 | */ |
59 | sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */ | 59 | sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */ |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * Prepare to handle 2 byte result. | 62 | * Prepare to handle 2 byte result. |
63 | */ | 63 | */ |
64 | if ((reg == DTT_READ_TEMP) || | 64 | if ((reg == DTT_READ_TEMP) || |
65 | (reg == DTT_TEMP_HYST) || | 65 | (reg == DTT_TEMP_HYST) || |
66 | (reg == DTT_TEMP_SET)) | 66 | (reg == DTT_TEMP_SET)) |
67 | dlen = 2; | 67 | dlen = 2; |
68 | else | 68 | else |
69 | dlen = 1; | 69 | dlen = 1; |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Now try to read the register. | 72 | * Now try to read the register. |
73 | */ | 73 | */ |
74 | if (i2c_read(sensor, reg, 1, data, dlen) != 0) | 74 | if (i2c_read(sensor, reg, 1, data, dlen) != 0) |
75 | return -1; | 75 | return -1; |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * Handle 2 byte result. | 78 | * Handle 2 byte result. |
79 | */ | 79 | */ |
80 | if (dlen == 2) | 80 | if (dlen == 2) |
81 | return ((int)((short)data[1] + (((short)data[0]) << 8))); | 81 | return ((int)((short)data[1] + (((short)data[0]) << 8))); |
82 | 82 | ||
83 | 83 | ||
84 | return (int)data[0]; | 84 | return (int)data[0]; |
85 | } /* dtt_read() */ | 85 | } /* dtt_read() */ |
86 | 86 | ||
87 | 87 | ||
88 | int dtt_write(int sensor, int reg, int val) | 88 | int dtt_write(int sensor, int reg, int val) |
89 | { | 89 | { |
90 | int dlen; | 90 | int dlen; |
91 | uchar data[2]; | 91 | uchar data[2]; |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Validate 'reg' param | 94 | * Validate 'reg' param |
95 | */ | 95 | */ |
96 | if ((reg < 0) || (reg > 3)) | 96 | if ((reg < 0) || (reg > 3)) |
97 | return 1; | 97 | return 1; |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * Calculate sensor address and register. | 100 | * Calculate sensor address and register. |
101 | */ | 101 | */ |
102 | sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */ | 102 | sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */ |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * Handle 2 byte values. | 105 | * Handle 2 byte values. |
106 | */ | 106 | */ |
107 | if ((reg == DTT_READ_TEMP) || | 107 | if ((reg == DTT_READ_TEMP) || |
108 | (reg == DTT_TEMP_HYST) || | 108 | (reg == DTT_TEMP_HYST) || |
109 | (reg == DTT_TEMP_SET)) { | 109 | (reg == DTT_TEMP_SET)) { |
110 | dlen = 2; | 110 | dlen = 2; |
111 | data[0] = (char)((val >> 8) & 0xff); /* MSB first */ | 111 | data[0] = (char)((val >> 8) & 0xff); /* MSB first */ |
112 | data[1] = (char)(val & 0xff); | 112 | data[1] = (char)(val & 0xff); |
113 | } else { | 113 | } else { |
114 | dlen = 1; | 114 | dlen = 1; |
115 | data[0] = (char)(val & 0xff); | 115 | data[0] = (char)(val & 0xff); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * Write value to register. | 119 | * Write value to register. |
120 | */ | 120 | */ |
121 | if (i2c_write(sensor, reg, 1, data, dlen) != 0) | 121 | if (i2c_write(sensor, reg, 1, data, dlen) != 0) |
122 | return 1; | 122 | return 1; |
123 | 123 | ||
124 | return 0; | 124 | return 0; |
125 | } /* dtt_write() */ | 125 | } /* dtt_write() */ |
126 | 126 | ||
127 | 127 | ||
128 | static int _dtt_init(int sensor) | 128 | static int _dtt_init(int sensor) |
129 | { | 129 | { |
130 | int val; | 130 | int val; |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * Setup TSET ( trip point ) register | 133 | * Setup TSET ( trip point ) register |
134 | */ | 134 | */ |
135 | val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; /* trip */ | 135 | val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; /* trip */ |
136 | if (dtt_write(sensor, DTT_TEMP_SET, val) != 0) | 136 | if (dtt_write(sensor, DTT_TEMP_SET, val) != 0) |
137 | return 1; | 137 | return 1; |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * Setup THYST ( untrip point ) register - Hysteresis | 140 | * Setup THYST ( untrip point ) register - Hysteresis |
141 | */ | 141 | */ |
142 | val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80; | 142 | val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80; |
143 | if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0) | 143 | if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0) |
144 | return 1; | 144 | return 1; |
145 | 145 | ||
146 | /* | 146 | /* |
147 | * Setup configuraton register | 147 | * Setup configuraton register |
148 | */ | 148 | */ |
149 | #ifdef CONFIG_DTT_AD7414 | 149 | #ifdef CONFIG_DTT_AD7414 |
150 | /* config = alert active low and disabled */ | 150 | /* config = alert active low and disabled */ |
151 | val = 0x60; | 151 | val = 0x60; |
152 | #else | 152 | #else |
153 | /* config = 6 sample integration, int mode, active low, and enable */ | 153 | /* config = 6 sample integration, int mode, active low, and enable */ |
154 | val = 0x18; | 154 | val = 0x18; |
155 | #endif | 155 | #endif |
156 | if (dtt_write(sensor, DTT_CONFIG, val) != 0) | 156 | if (dtt_write(sensor, DTT_CONFIG, val) != 0) |
157 | return 1; | 157 | return 1; |
158 | 158 | ||
159 | return 0; | 159 | return 0; |
160 | } /* _dtt_init() */ | 160 | } /* _dtt_init() */ |
161 | 161 | ||
162 | 162 | ||
163 | int dtt_init (void) | 163 | int dtt_init (void) |
164 | { | 164 | { |
165 | int i; | 165 | int i; |
166 | unsigned char sensors[] = CONFIG_DTT_SENSORS; | 166 | unsigned char sensors[] = CONFIG_DTT_SENSORS; |
167 | const char *const header = "DTT: "; | 167 | const char *const header = "DTT: "; |
168 | 168 | ||
169 | for (i = 0; i < sizeof(sensors); i++) { | 169 | for (i = 0; i < sizeof(sensors); i++) { |
170 | if (_dtt_init(sensors[i]) != 0) | 170 | if (_dtt_init(sensors[i]) != 0) |
171 | printf("%s%d FAILED INIT\n", header, i+1); | 171 | printf("%s%d FAILED INIT\n", header, i+1); |
172 | else | 172 | else |
173 | printf("%s%d is %i C\n", header, i+1, | 173 | printf("%s%d is %i C\n", header, i+1, |
174 | dtt_get_temp(sensors[i])); | 174 | dtt_get_temp(sensors[i])); |
175 | } | 175 | } |
176 | 176 | ||
177 | return (0); | 177 | return (0); |
178 | } /* dtt_init() */ | 178 | } /* dtt_init() */ |
179 | 179 | ||
180 | int dtt_get_temp(int sensor) | 180 | int dtt_get_temp(int sensor) |
181 | { | 181 | { |
182 | return (dtt_read(sensor, DTT_READ_TEMP) / 256); | 182 | int const ret = dtt_read(sensor, DTT_READ_TEMP); |
183 | |||
184 | if (ret < 0) { | ||
185 | printf("DTT temperature read failed.\n"); | ||
186 | return 0; | ||
187 | } | ||
188 | return (int)((int16_t) ret / 256); | ||
183 | } /* dtt_get_temp() */ | 189 | } /* dtt_get_temp() */ |
184 | 190 | ||
185 | #endif /* CONFIG_DTT_LM75 */ | 191 | #endif /* CONFIG_DTT_LM75 */ |
186 | 192 |