diff options
author | Karl Komierowski <karl.komierowski@stericsson.com> | 2011-08-10 09:09:43 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-10-24 08:09:10 -0400 |
commit | bd4a40b57b13907b4fe01b6c605be56d8f3733fe (patch) | |
tree | 0a17816675cb65cc54c1262eb1216d70dc2a8ac2 /drivers/mfd | |
parent | 981c65a9b3e24029f64bd45c7a92f901899a033e (diff) |
mfd: Refactor ab8500 GPADC API, add raw access
Refactor the GPADC interface to avoid bugs in calling code:
- ab8500_gpadc_[convert|read_raw|ad_to_voltage] clarifies
each functions use case, *convert wraps *read_raw, and we
can access raw ADC values properly.
- Renamed gpadc function arguments from "input" to "channel" to
clarify use, so we don't get confused again.
Signed-off-by: Kalle Komierowski <kalle.komierowski@stericsson.com>
Reviewed-by: Mattias Wallin <mattias.wallin@stericsson.com>
Reviewed-by: John Beckett <john.beckett@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index f16afb234ff9..e985d1701a83 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -143,12 +143,15 @@ struct ab8500_gpadc *ab8500_gpadc_get(char *name) | |||
143 | } | 143 | } |
144 | EXPORT_SYMBOL(ab8500_gpadc_get); | 144 | EXPORT_SYMBOL(ab8500_gpadc_get); |
145 | 145 | ||
146 | static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input, | 146 | /** |
147 | * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage | ||
148 | */ | ||
149 | int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | ||
147 | int ad_value) | 150 | int ad_value) |
148 | { | 151 | { |
149 | int res; | 152 | int res; |
150 | 153 | ||
151 | switch (input) { | 154 | switch (channel) { |
152 | case MAIN_CHARGER_V: | 155 | case MAIN_CHARGER_V: |
153 | /* For some reason we don't have calibrated data */ | 156 | /* For some reason we don't have calibrated data */ |
154 | if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) { | 157 | if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) { |
@@ -232,18 +235,46 @@ static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input, | |||
232 | } | 235 | } |
233 | return res; | 236 | return res; |
234 | } | 237 | } |
238 | EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); | ||
235 | 239 | ||
236 | /** | 240 | /** |
237 | * ab8500_gpadc_convert() - gpadc conversion | 241 | * ab8500_gpadc_convert() - gpadc conversion |
238 | * @input: analog input to be converted to digital data | 242 | * @channel: analog channel to be converted to digital data |
239 | * | 243 | * |
240 | * This function converts the selected analog i/p to digital | 244 | * This function converts the selected analog i/p to digital |
241 | * data. | 245 | * data. |
242 | */ | 246 | */ |
243 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | 247 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel) |
248 | { | ||
249 | int ad_value; | ||
250 | int voltage; | ||
251 | |||
252 | ad_value = ab8500_gpadc_read_raw(gpadc, channel); | ||
253 | if (ad_value < 0) { | ||
254 | dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel); | ||
255 | return ad_value; | ||
256 | } | ||
257 | |||
258 | voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); | ||
259 | |||
260 | if (voltage < 0) | ||
261 | dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:" | ||
262 | " %d AD: 0x%x\n", channel, ad_value); | ||
263 | |||
264 | return voltage; | ||
265 | } | ||
266 | EXPORT_SYMBOL(ab8500_gpadc_convert); | ||
267 | |||
268 | /** | ||
269 | * ab8500_gpadc_read_raw() - gpadc read | ||
270 | * @channel: analog channel to be read | ||
271 | * | ||
272 | * This function obtains the raw ADC value, this then needs | ||
273 | * to be converted by calling ab8500_gpadc_ad_to_voltage() | ||
274 | */ | ||
275 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | ||
244 | { | 276 | { |
245 | int ret; | 277 | int ret; |
246 | u16 data = 0; | ||
247 | int looplimit = 0; | 278 | int looplimit = 0; |
248 | u8 val, low_data, high_data; | 279 | u8 val, low_data, high_data; |
249 | 280 | ||
@@ -278,9 +309,9 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
278 | goto out; | 309 | goto out; |
279 | } | 310 | } |
280 | 311 | ||
281 | /* Select the input source and set average samples to 16 */ | 312 | /* Select the channel source and set average samples to 16 */ |
282 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 313 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
283 | AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16)); | 314 | AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16)); |
284 | if (ret < 0) { | 315 | if (ret < 0) { |
285 | dev_err(gpadc->dev, | 316 | dev_err(gpadc->dev, |
286 | "gpadc_conversion: set avg samples failed\n"); | 317 | "gpadc_conversion: set avg samples failed\n"); |
@@ -292,7 +323,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
292 | * charging current sense if it needed, ABB 3.0 needs some special | 323 | * charging current sense if it needed, ABB 3.0 needs some special |
293 | * treatment too. | 324 | * treatment too. |
294 | */ | 325 | */ |
295 | switch (input) { | 326 | switch (channel) { |
296 | case MAIN_CHARGER_C: | 327 | case MAIN_CHARGER_C: |
297 | case USB_CHARGER_C: | 328 | case USB_CHARGER_C: |
298 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 329 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, |
@@ -359,7 +390,6 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
359 | goto out; | 390 | goto out; |
360 | } | 391 | } |
361 | 392 | ||
362 | data = (high_data << 8) | low_data; | ||
363 | /* Disable GPADC */ | 393 | /* Disable GPADC */ |
364 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 394 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
365 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 395 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
@@ -370,8 +400,8 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
370 | /* Disable VTVout LDO this is required for GPADC */ | 400 | /* Disable VTVout LDO this is required for GPADC */ |
371 | regulator_disable(gpadc->regu); | 401 | regulator_disable(gpadc->regu); |
372 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 402 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
373 | ret = ab8500_gpadc_ad_to_voltage(gpadc, input, data); | 403 | |
374 | return ret; | 404 | return (high_data << 8) | low_data; |
375 | 405 | ||
376 | out: | 406 | out: |
377 | /* | 407 | /* |
@@ -385,10 +415,10 @@ out: | |||
385 | regulator_disable(gpadc->regu); | 415 | regulator_disable(gpadc->regu); |
386 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 416 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
387 | dev_err(gpadc->dev, | 417 | dev_err(gpadc->dev, |
388 | "gpadc_conversion: Failed to AD convert channel %d\n", input); | 418 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); |
389 | return ret; | 419 | return ret; |
390 | } | 420 | } |
391 | EXPORT_SYMBOL(ab8500_gpadc_convert); | 421 | EXPORT_SYMBOL(ab8500_gpadc_read_raw); |
392 | 422 | ||
393 | /** | 423 | /** |
394 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion | 424 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion |