aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2012-04-22 23:58:51 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2012-05-20 22:41:49 -0400
commitdbe43a62762d2a6430cf6ed65d3459ce1e8ed46c (patch)
treeec2d53d1747a522dd6bb2277ddea04ffe0f9a790 /drivers/hwmon
parent425d247680d050fe3ee7e53b9cf0240bf6b4b351 (diff)
hwmon: (ntc_thermistor) Optimize and fix build warning
The following build warning is seen in some configurations: drivers/hwmon/ntc_thermistor.c: In function 'ntc_show_temp': drivers/hwmon/ntc_thermistor.c:293: warning: 'temp' may be used uninitialized in this function Fix the problem by re-arranging the code to overload return values with error codes, and by avoiding error returns whenever possible. Specifically, Simplify lookup_comp() to not return an error. Instead, return i_low == i_high if there is an exact match, or if the ohm value is outside the lookup table range. Modify get_temp_mC() to not return an error. Since it only returns an error after lookup_comp() returned an error, this is quite straightforward after above change. Separate ntc_thermistor_read() into a function to read the resistor value (which can return an error), and the call to get_temp_mC() which doesn't. Call the functions directly from ntc_show_temp(). Code was tested using a test program, comparing the result of the old and new versions of get_temp_mC() for resistor values between 0 and 2,000,000 ohm. As a side effect, this patch reduces code size by approximately 400 bytes on x86_64. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Cc: Donggeun Kim <dg77.kim@samsung.com> Reviewed-by: Robert Coulson <robert.coulson@ericsson.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/ntc_thermistor.c164
1 files changed, 80 insertions, 84 deletions
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index b31bf1d3172a..ea163866789a 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -134,8 +134,7 @@ static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
134 return div64_u64(dividend, divisor); 134 return div64_u64(dividend, divisor);
135} 135}
136 136
137static unsigned int get_ohm_of_thermistor(struct ntc_data *data, 137static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uV)
138 unsigned int uV)
139{ 138{
140 struct ntc_thermistor_platform_data *pdata = data->pdata; 139 struct ntc_thermistor_platform_data *pdata = data->pdata;
141 u64 mV = uV / 1000; 140 u64 mV = uV / 1000;
@@ -146,12 +145,12 @@ static unsigned int get_ohm_of_thermistor(struct ntc_data *data,
146 145
147 if (mV == 0) { 146 if (mV == 0) {
148 if (pdata->connect == NTC_CONNECTED_POSITIVE) 147 if (pdata->connect == NTC_CONNECTED_POSITIVE)
149 return UINT_MAX; 148 return INT_MAX;
150 return 0; 149 return 0;
151 } 150 }
152 if (mV >= pmV) 151 if (mV >= pmV)
153 return (pdata->connect == NTC_CONNECTED_POSITIVE) ? 152 return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
154 0 : UINT_MAX; 153 0 : INT_MAX;
155 154
156 if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0) 155 if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0)
157 N = div64_u64_safe(pdO * (pmV - mV), mV); 156 N = div64_u64_safe(pdO * (pmV - mV), mV);
@@ -163,113 +162,109 @@ static unsigned int get_ohm_of_thermistor(struct ntc_data *data,
163 else 162 else
164 N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV); 163 N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV);
165 164
166 return (unsigned int) N; 165 if (N > INT_MAX)
166 N = INT_MAX;
167 return N;
167} 168}
168 169
169static int lookup_comp(struct ntc_data *data, 170static void lookup_comp(struct ntc_data *data, unsigned int ohm,
170 unsigned int ohm, int *i_low, int *i_high) 171 int *i_low, int *i_high)
171{ 172{
172 int start, end, mid = -1; 173 int start, end, mid;
174
175 /*
176 * Handle special cases: Resistance is higher than or equal to
177 * resistance in first table entry, or resistance is lower or equal
178 * to resistance in last table entry.
179 * In these cases, return i_low == i_high, either pointing to the
180 * beginning or to the end of the table depending on the condition.
181 */
182 if (ohm >= data->comp[0].ohm) {
183 *i_low = 0;
184 *i_high = 0;
185 return;
186 }
187 if (ohm <= data->comp[data->n_comp - 1].ohm) {
188 *i_low = data->n_comp - 1;
189 *i_high = data->n_comp - 1;
190 return;
191 }
173 192
174 /* Do a binary search on compensation table */ 193 /* Do a binary search on compensation table */
175 start = 0; 194 start = 0;
176 end = data->n_comp; 195 end = data->n_comp;
177 196 while (start < end) {
178 while (end > start) {
179 mid = start + (end - start) / 2; 197 mid = start + (end - start) / 2;
180 if (data->comp[mid].ohm < ohm) 198 /*
199 * start <= mid < end
200 * data->comp[start].ohm > ohm >= data->comp[end].ohm
201 *
202 * We could check for "ohm == data->comp[mid].ohm" here, but
203 * that is a quite unlikely condition, and we would have to
204 * check again after updating start. Check it at the end instead
205 * for simplicity.
206 */
207 if (ohm >= data->comp[mid].ohm) {
181 end = mid; 208 end = mid;
182 else if (data->comp[mid].ohm > ohm)
183 start = mid + 1;
184 else
185 break;
186 }
187
188 if (mid == 0) {
189 if (data->comp[mid].ohm > ohm) {
190 *i_high = mid;
191 *i_low = mid + 1;
192 return 0;
193 } else { 209 } else {
194 *i_low = mid; 210 start = mid + 1;
195 *i_high = -1; 211 /*
196 return -EINVAL; 212 * ohm >= data->comp[start].ohm might be true here,
197 } 213 * since we set start to mid + 1. In that case, we are
198 } 214 * done. We could keep going, but the condition is quite
199 if (mid == (data->n_comp - 1)) { 215 * likely to occur, so it is worth checking for it.
200 if (data->comp[mid].ohm <= ohm) { 216 */
201 *i_low = mid; 217 if (ohm >= data->comp[start].ohm)
202 *i_high = mid - 1; 218 end = start;
203 return 0;
204 } else {
205 *i_low = -1;
206 *i_high = mid;
207 return -EINVAL;
208 } 219 }
220 /*
221 * start <= end
222 * data->comp[start].ohm >= ohm >= data->comp[end].ohm
223 */
209 } 224 }
210 225 /*
211 if (data->comp[mid].ohm <= ohm) { 226 * start == end
212 *i_low = mid; 227 * ohm >= data->comp[end].ohm
213 *i_high = mid - 1; 228 */
214 } else { 229 *i_low = end;
215 *i_low = mid + 1; 230 if (ohm == data->comp[end].ohm)
216 *i_high = mid; 231 *i_high = end;
217 } 232 else
218 233 *i_high = end - 1;
219 return 0;
220} 234}
221 235
222static int get_temp_mC(struct ntc_data *data, unsigned int ohm, int *temp) 236static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
223{ 237{
224 int low, high; 238 int low, high;
225 int ret; 239 int temp;
226 240
227 ret = lookup_comp(data, ohm, &low, &high); 241 lookup_comp(data, ohm, &low, &high);
228 if (ret) { 242 if (low == high) {
229 /* Unable to use linear approximation */ 243 /* Unable to use linear approximation */
230 if (low != -1) 244 temp = data->comp[low].temp_C * 1000;
231 *temp = data->comp[low].temp_C * 1000;
232 else if (high != -1)
233 *temp = data->comp[high].temp_C * 1000;
234 else
235 return ret;
236 } else { 245 } else {
237 *temp = data->comp[low].temp_C * 1000 + 246 temp = data->comp[low].temp_C * 1000 +
238 ((data->comp[high].temp_C - data->comp[low].temp_C) * 247 ((data->comp[high].temp_C - data->comp[low].temp_C) *
239 1000 * ((int)ohm - (int)data->comp[low].ohm)) / 248 1000 * ((int)ohm - (int)data->comp[low].ohm)) /
240 ((int)data->comp[high].ohm - (int)data->comp[low].ohm); 249 ((int)data->comp[high].ohm - (int)data->comp[low].ohm);
241 } 250 }
242 251 return temp;
243 return 0;
244} 252}
245 253
246static int ntc_thermistor_read(struct ntc_data *data, int *temp) 254static int ntc_thermistor_get_ohm(struct ntc_data *data)
247{ 255{
248 int ret; 256 int read_uV;
249 int read_ohm, read_uV; 257
250 unsigned int ohm = 0; 258 if (data->pdata->read_ohm)
251 259 return data->pdata->read_ohm();
252 if (data->pdata->read_ohm) {
253 read_ohm = data->pdata->read_ohm();
254 if (read_ohm < 0)
255 return read_ohm;
256 ohm = (unsigned int)read_ohm;
257 }
258 260
259 if (data->pdata->read_uV) { 261 if (data->pdata->read_uV) {
260 read_uV = data->pdata->read_uV(); 262 read_uV = data->pdata->read_uV();
261 if (read_uV < 0) 263 if (read_uV < 0)
262 return read_uV; 264 return read_uV;
263 ohm = get_ohm_of_thermistor(data, (unsigned int)read_uV); 265 return get_ohm_of_thermistor(data, read_uV);
264 }
265
266 ret = get_temp_mC(data, ohm, temp);
267 if (ret) {
268 dev_dbg(data->dev, "Sensor reading function not available.\n");
269 return ret;
270 } 266 }
271 267 return -EINVAL;
272 return 0;
273} 268}
274 269
275static ssize_t ntc_show_name(struct device *dev, 270static ssize_t ntc_show_name(struct device *dev,
@@ -290,12 +285,13 @@ static ssize_t ntc_show_temp(struct device *dev,
290 struct device_attribute *attr, char *buf) 285 struct device_attribute *attr, char *buf)
291{ 286{
292 struct ntc_data *data = dev_get_drvdata(dev); 287 struct ntc_data *data = dev_get_drvdata(dev);
293 int temp, ret; 288 int ohm;
294 289
295 ret = ntc_thermistor_read(data, &temp); 290 ohm = ntc_thermistor_get_ohm(data);
296 if (ret) 291 if (ohm < 0)
297 return ret; 292 return ohm;
298 return sprintf(buf, "%d\n", temp); 293
294 return sprintf(buf, "%d\n", get_temp_mC(data, ohm));
299} 295}
300 296
301static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0); 297static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0);