diff options
author | Lee Jones <lee.jones@linaro.org> | 2013-02-11 05:49:41 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-03-06 23:28:35 -0500 |
commit | 7c8f023616f89c3796331cece68b7efdc5a0b1ca (patch) | |
tree | 4c165cfb443660beb1f9e333ee22e17bddd34d51 /drivers/mfd | |
parent | bc6b4132bcae4b8e59766ba2dae8f377009b26d0 (diff) |
mfd: ab8500-gpadc: Optimise GPADC driver
Optimise GPADC driver:
* for code readability and maintenance by grouping similar cheking
* for performance by grouping several writing to control register
Signed-off-by: Alexandre Bourdiol <alexandre.bourdiol@stericsson.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 212 |
1 files changed, 55 insertions, 157 deletions
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index e3535c74d5fe..af1db2a45e86 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -360,7 +360,12 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
360 | { | 360 | { |
361 | int ret; | 361 | int ret; |
362 | int looplimit = 0; | 362 | int looplimit = 0; |
363 | unsigned long completion_timeout; | ||
363 | u8 val, low_data, high_data, low_data2, high_data2; | 364 | u8 val, low_data, high_data, low_data2, high_data2; |
365 | u8 val_reg1 = 0; | ||
366 | unsigned int delay_min = 0; | ||
367 | unsigned int delay_max = 0; | ||
368 | u8 data_low_addr, data_high_addr; | ||
364 | 369 | ||
365 | if (!gpadc) | 370 | if (!gpadc) |
366 | return -ENODEV; | 371 | return -ENODEV; |
@@ -392,12 +397,7 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
392 | } | 397 | } |
393 | 398 | ||
394 | /* Enable GPADC */ | 399 | /* Enable GPADC */ |
395 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 400 | val_reg1 |= EN_GPADC; |
396 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC); | ||
397 | if (ret < 0) { | ||
398 | dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n"); | ||
399 | goto out; | ||
400 | } | ||
401 | 401 | ||
402 | /* Select the channel source and set average samples */ | 402 | /* Select the channel source and set average samples */ |
403 | switch (avg_sample) { | 403 | switch (avg_sample) { |
@@ -415,9 +415,13 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
415 | break; | 415 | break; |
416 | } | 416 | } |
417 | 417 | ||
418 | if (conv_type == ADC_HW) | 418 | if (conv_type == ADC_HW) { |
419 | ret = abx500_set_register_interruptible(gpadc->dev, | 419 | ret = abx500_set_register_interruptible(gpadc->dev, |
420 | AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val); | 420 | AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val); |
421 | val_reg1 |= EN_TRIG_EDGE; | ||
422 | if (trig_edge) | ||
423 | val_reg1 |= EN_FALLING; | ||
424 | } | ||
421 | else | 425 | else |
422 | ret = abx500_set_register_interruptible(gpadc->dev, | 426 | ret = abx500_set_register_interruptible(gpadc->dev, |
423 | AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val); | 427 | AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val); |
@@ -432,123 +436,42 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
432 | * charging current sense if it needed, ABB 3.0 needs some special | 436 | * charging current sense if it needed, ABB 3.0 needs some special |
433 | * treatment too. | 437 | * treatment too. |
434 | */ | 438 | */ |
435 | if ((conv_type == ADC_HW) && (trig_edge)) { | ||
436 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | ||
437 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
438 | EN_FALLING, EN_FALLING); | ||
439 | } | ||
440 | |||
441 | switch (channel) { | 439 | switch (channel) { |
442 | case MAIN_CHARGER_C: | 440 | case MAIN_CHARGER_C: |
443 | case USB_CHARGER_C: | 441 | case USB_CHARGER_C: |
444 | if (conv_type == ADC_HW) | 442 | val_reg1 |= EN_BUF | EN_ICHAR; |
445 | ret = abx500_mask_and_set_register_interruptible( | ||
446 | gpadc->dev, | ||
447 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
448 | EN_BUF | EN_ICHAR | EN_TRIG_EDGE, | ||
449 | EN_BUF | EN_ICHAR | EN_TRIG_EDGE); | ||
450 | else | ||
451 | ret = abx500_mask_and_set_register_interruptible( | ||
452 | gpadc->dev, | ||
453 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
454 | EN_BUF | EN_ICHAR, | ||
455 | EN_BUF | EN_ICHAR); | ||
456 | break; | ||
457 | |||
458 | case XTAL_TEMP: | ||
459 | if (conv_type == ADC_HW) | ||
460 | ret = abx500_mask_and_set_register_interruptible( | ||
461 | gpadc->dev, | ||
462 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
463 | EN_BUF | EN_TRIG_EDGE, | ||
464 | EN_BUF | EN_TRIG_EDGE); | ||
465 | else | ||
466 | ret = abx500_mask_and_set_register_interruptible( | ||
467 | gpadc->dev, | ||
468 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
469 | EN_BUF , | ||
470 | EN_BUF); | ||
471 | break; | ||
472 | |||
473 | case VBAT_TRUE_MEAS: | ||
474 | if (conv_type == ADC_HW) | ||
475 | ret = abx500_mask_and_set_register_interruptible( | ||
476 | gpadc->dev, | ||
477 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
478 | EN_BUF | EN_TRIG_EDGE, | ||
479 | EN_BUF | EN_TRIG_EDGE); | ||
480 | else | ||
481 | ret = abx500_mask_and_set_register_interruptible( | ||
482 | gpadc->dev, | ||
483 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
484 | EN_BUF , | ||
485 | EN_BUF); | ||
486 | break; | ||
487 | |||
488 | case BAT_CTRL_AND_IBAT: | ||
489 | case VBAT_MEAS_AND_IBAT: | ||
490 | case VBAT_TRUE_MEAS_AND_IBAT: | ||
491 | case BAT_TEMP_AND_IBAT: | ||
492 | if (conv_type == ADC_HW) | ||
493 | ret = abx500_mask_and_set_register_interruptible( | ||
494 | gpadc->dev, | ||
495 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
496 | EN_TRIG_EDGE, | ||
497 | EN_TRIG_EDGE); | ||
498 | else | ||
499 | ret = abx500_mask_and_set_register_interruptible( | ||
500 | gpadc->dev, | ||
501 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
502 | EN_BUF, | ||
503 | 0); | ||
504 | break; | 443 | break; |
505 | |||
506 | case BTEMP_BALL: | 444 | case BTEMP_BALL: |
507 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { | 445 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { |
508 | if (conv_type == ADC_HW) | 446 | val_reg1 |= EN_BUF | BTEMP_PULL_UP; |
509 | /* Turn on btemp pull-up on ABB 3.0 */ | 447 | /* |
510 | ret = abx500_mask_and_set_register_interruptible | 448 | * Delay might be needed for ABB8500 cut 3.0, if not, |
511 | (gpadc->dev, | 449 | * remove when hardware will be availible |
512 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | 450 | */ |
513 | EN_BUF | BTEMP_PULL_UP | EN_TRIG_EDGE, | 451 | delay_min = 1000; /* Delay in micro seconds */ |
514 | EN_BUF | BTEMP_PULL_UP | EN_TRIG_EDGE); | 452 | delay_max = 10000; /* large range to optimise sleep mode */ |
515 | else | ||
516 | ret = abx500_mask_and_set_register_interruptible | ||
517 | (gpadc->dev, | ||
518 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
519 | EN_BUF | BTEMP_PULL_UP, | ||
520 | EN_BUF | BTEMP_PULL_UP); | ||
521 | |||
522 | /* | ||
523 | * Delay might be needed for ABB8500 cut 3.0, if not, remove | ||
524 | * when hardware will be available | ||
525 | */ | ||
526 | usleep_range(1000, 1000); | ||
527 | break; | 453 | break; |
528 | } | 454 | } |
529 | /* Intentional fallthrough */ | 455 | /* Intentional fallthrough */ |
530 | default: | 456 | default: |
531 | if (conv_type == ADC_HW) | 457 | val_reg1 |= EN_BUF; |
532 | ret = abx500_mask_and_set_register_interruptible( | ||
533 | gpadc->dev, | ||
534 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
535 | EN_BUF | EN_TRIG_EDGE, | ||
536 | EN_BUF | EN_TRIG_EDGE); | ||
537 | else | ||
538 | ret = abx500_mask_and_set_register_interruptible( | ||
539 | gpadc->dev, | ||
540 | AB8500_GPADC, | ||
541 | AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF); | ||
542 | break; | 458 | break; |
543 | } | 459 | } |
460 | |||
461 | /* Write configuration to register */ | ||
462 | ret = abx500_set_register_interruptible(gpadc->dev, | ||
463 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, val_reg1); | ||
544 | if (ret < 0) { | 464 | if (ret < 0) { |
545 | dev_err(gpadc->dev, | 465 | dev_err(gpadc->dev, |
546 | "gpadc_conversion: select falling edge failed\n"); | 466 | "gpadc_conversion: set Control register failed\n"); |
547 | goto out; | 467 | goto out; |
548 | } | 468 | } |
549 | 469 | ||
550 | /* Set trigger delay timer */ | 470 | if (delay_min != 0) |
471 | usleep_range(delay_min, delay_max); | ||
472 | |||
551 | if (conv_type == ADC_HW) { | 473 | if (conv_type == ADC_HW) { |
474 | /* Set trigger delay timer */ | ||
552 | ret = abx500_set_register_interruptible(gpadc->dev, | 475 | ret = abx500_set_register_interruptible(gpadc->dev, |
553 | AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer); | 476 | AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer); |
554 | if (ret < 0) { | 477 | if (ret < 0) { |
@@ -556,10 +479,11 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
556 | "gpadc_conversion: trig timer failed\n"); | 479 | "gpadc_conversion: trig timer failed\n"); |
557 | goto out; | 480 | goto out; |
558 | } | 481 | } |
559 | } | 482 | completion_timeout = 2 * HZ; |
560 | 483 | data_low_addr = AB8500_GPADC_AUTODATAL_REG; | |
561 | /* Start SW conversion */ | 484 | data_high_addr = AB8500_GPADC_AUTODATAH_REG; |
562 | if (conv_type == ADC_SW) { | 485 | } else { |
486 | /* Start SW conversion */ | ||
563 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 487 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, |
564 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | 488 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, |
565 | ADC_SW_CONV, ADC_SW_CONV); | 489 | ADC_SW_CONV, ADC_SW_CONV); |
@@ -568,61 +492,35 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
568 | "gpadc_conversion: start s/w conv failed\n"); | 492 | "gpadc_conversion: start s/w conv failed\n"); |
569 | goto out; | 493 | goto out; |
570 | } | 494 | } |
495 | completion_timeout = msecs_to_jiffies(CONVERSION_TIME); | ||
496 | data_low_addr = AB8500_GPADC_MANDATAL_REG; | ||
497 | data_high_addr = AB8500_GPADC_MANDATAH_REG; | ||
571 | } | 498 | } |
572 | 499 | ||
573 | /* wait for completion of conversion */ | 500 | /* wait for completion of conversion */ |
574 | if (conv_type == ADC_HW) { | 501 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
575 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | 502 | completion_timeout)) { |
576 | 2 * HZ)) { | 503 | dev_err(gpadc->dev, |
577 | dev_err(gpadc->dev, | 504 | "timeout didn't receive GPADC conv interrupt\n"); |
578 | "timeout didn't receive hw GPADC conv interrupt\n"); | 505 | ret = -EINVAL; |
579 | ret = -EINVAL; | 506 | goto out; |
580 | goto out; | ||
581 | } | ||
582 | } else { | ||
583 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | ||
584 | msecs_to_jiffies(CONVERSION_TIME))) { | ||
585 | dev_err(gpadc->dev, | ||
586 | "timeout didn't receive sw GPADC conv interrupt\n"); | ||
587 | ret = -EINVAL; | ||
588 | goto out; | ||
589 | } | ||
590 | } | 507 | } |
591 | 508 | ||
592 | /* Read the converted RAW data */ | 509 | /* Read the converted RAW data */ |
593 | if (conv_type == ADC_HW) { | 510 | ret = abx500_get_register_interruptible(gpadc->dev, |
594 | ret = abx500_get_register_interruptible(gpadc->dev, | 511 | AB8500_GPADC, data_low_addr, &low_data); |
595 | AB8500_GPADC, AB8500_GPADC_AUTODATAL_REG, &low_data); | 512 | if (ret < 0) { |
596 | if (ret < 0) { | 513 | dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n"); |
597 | dev_err(gpadc->dev, | 514 | goto out; |
598 | "gpadc_conversion: read hw low data failed\n"); | 515 | } |
599 | goto out; | ||
600 | } | ||
601 | |||
602 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
603 | AB8500_GPADC, AB8500_GPADC_AUTODATAH_REG, &high_data); | ||
604 | if (ret < 0) { | ||
605 | dev_err(gpadc->dev, | ||
606 | "gpadc_conversion: read hw high data failed\n"); | ||
607 | goto out; | ||
608 | } | ||
609 | } else { | ||
610 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
611 | AB8500_GPADC, AB8500_GPADC_MANDATAL_REG, &low_data); | ||
612 | if (ret < 0) { | ||
613 | dev_err(gpadc->dev, | ||
614 | "gpadc_conversion: read sw low data failed\n"); | ||
615 | goto out; | ||
616 | } | ||
617 | 516 | ||
618 | ret = abx500_get_register_interruptible(gpadc->dev, | 517 | ret = abx500_get_register_interruptible(gpadc->dev, |
619 | AB8500_GPADC, AB8500_GPADC_MANDATAH_REG, &high_data); | 518 | AB8500_GPADC, data_high_addr, &high_data); |
620 | if (ret < 0) { | 519 | if (ret < 0) { |
621 | dev_err(gpadc->dev, | 520 | dev_err(gpadc->dev, "gpadc_conversion: read high data failed\n"); |
622 | "gpadc_conversion: read sw high data failed\n"); | 521 | goto out; |
623 | goto out; | ||
624 | } | ||
625 | } | 522 | } |
523 | |||
626 | /* Check if double convertion is required */ | 524 | /* Check if double convertion is required */ |
627 | if ((channel == BAT_CTRL_AND_IBAT) || | 525 | if ((channel == BAT_CTRL_AND_IBAT) || |
628 | (channel == VBAT_MEAS_AND_IBAT) || | 526 | (channel == VBAT_MEAS_AND_IBAT) || |