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>
This commit is contained in:
parent
bc6b4132bc
commit
7c8f023616
@ -360,7 +360,12 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int looplimit = 0;
|
int looplimit = 0;
|
||||||
|
unsigned long completion_timeout;
|
||||||
u8 val, low_data, high_data, low_data2, high_data2;
|
u8 val, low_data, high_data, low_data2, high_data2;
|
||||||
|
u8 val_reg1 = 0;
|
||||||
|
unsigned int delay_min = 0;
|
||||||
|
unsigned int delay_max = 0;
|
||||||
|
u8 data_low_addr, data_high_addr;
|
||||||
|
|
||||||
if (!gpadc)
|
if (!gpadc)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -392,12 +397,7 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Enable GPADC */
|
/* Enable GPADC */
|
||||||
ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
|
val_reg1 |= EN_GPADC;
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the channel source and set average samples */
|
/* Select the channel source and set average samples */
|
||||||
switch (avg_sample) {
|
switch (avg_sample) {
|
||||||
@ -415,9 +415,13 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conv_type == ADC_HW)
|
if (conv_type == ADC_HW) {
|
||||||
ret = abx500_set_register_interruptible(gpadc->dev,
|
ret = abx500_set_register_interruptible(gpadc->dev,
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val);
|
AB8500_GPADC, AB8500_GPADC_CTRL3_REG, val);
|
||||||
|
val_reg1 |= EN_TRIG_EDGE;
|
||||||
|
if (trig_edge)
|
||||||
|
val_reg1 |= EN_FALLING;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret = abx500_set_register_interruptible(gpadc->dev,
|
ret = abx500_set_register_interruptible(gpadc->dev,
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val);
|
AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val);
|
||||||
@ -432,123 +436,42 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
|
|||||||
* charging current sense if it needed, ABB 3.0 needs some special
|
* charging current sense if it needed, ABB 3.0 needs some special
|
||||||
* treatment too.
|
* treatment too.
|
||||||
*/
|
*/
|
||||||
if ((conv_type == ADC_HW) && (trig_edge)) {
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_FALLING, EN_FALLING);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
case MAIN_CHARGER_C:
|
case MAIN_CHARGER_C:
|
||||||
case USB_CHARGER_C:
|
case USB_CHARGER_C:
|
||||||
if (conv_type == ADC_HW)
|
val_reg1 |= EN_BUF | EN_ICHAR;
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF | EN_ICHAR | EN_TRIG_EDGE,
|
|
||||||
EN_BUF | EN_ICHAR | EN_TRIG_EDGE);
|
|
||||||
else
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF | EN_ICHAR,
|
|
||||||
EN_BUF | EN_ICHAR);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XTAL_TEMP:
|
|
||||||
if (conv_type == ADC_HW)
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF | EN_TRIG_EDGE,
|
|
||||||
EN_BUF | EN_TRIG_EDGE);
|
|
||||||
else
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF ,
|
|
||||||
EN_BUF);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VBAT_TRUE_MEAS:
|
|
||||||
if (conv_type == ADC_HW)
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF | EN_TRIG_EDGE,
|
|
||||||
EN_BUF | EN_TRIG_EDGE);
|
|
||||||
else
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF ,
|
|
||||||
EN_BUF);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BAT_CTRL_AND_IBAT:
|
|
||||||
case VBAT_MEAS_AND_IBAT:
|
|
||||||
case VBAT_TRUE_MEAS_AND_IBAT:
|
|
||||||
case BAT_TEMP_AND_IBAT:
|
|
||||||
if (conv_type == ADC_HW)
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_TRIG_EDGE,
|
|
||||||
EN_TRIG_EDGE);
|
|
||||||
else
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF,
|
|
||||||
0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BTEMP_BALL:
|
case BTEMP_BALL:
|
||||||
if (!is_ab8500_2p0_or_earlier(gpadc->parent)) {
|
if (!is_ab8500_2p0_or_earlier(gpadc->parent)) {
|
||||||
if (conv_type == ADC_HW)
|
val_reg1 |= EN_BUF | BTEMP_PULL_UP;
|
||||||
/* Turn on btemp pull-up on ABB 3.0 */
|
/*
|
||||||
ret = abx500_mask_and_set_register_interruptible
|
* Delay might be needed for ABB8500 cut 3.0, if not,
|
||||||
(gpadc->dev,
|
* remove when hardware will be availible
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
*/
|
||||||
EN_BUF | BTEMP_PULL_UP | EN_TRIG_EDGE,
|
delay_min = 1000; /* Delay in micro seconds */
|
||||||
EN_BUF | BTEMP_PULL_UP | EN_TRIG_EDGE);
|
delay_max = 10000; /* large range to optimise sleep mode */
|
||||||
else
|
|
||||||
ret = abx500_mask_and_set_register_interruptible
|
|
||||||
(gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF | BTEMP_PULL_UP,
|
|
||||||
EN_BUF | BTEMP_PULL_UP);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delay might be needed for ABB8500 cut 3.0, if not, remove
|
|
||||||
* when hardware will be available
|
|
||||||
*/
|
|
||||||
usleep_range(1000, 1000);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Intentional fallthrough */
|
/* Intentional fallthrough */
|
||||||
default:
|
default:
|
||||||
if (conv_type == ADC_HW)
|
val_reg1 |= EN_BUF;
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
|
||||||
EN_BUF | EN_TRIG_EDGE,
|
|
||||||
EN_BUF | EN_TRIG_EDGE);
|
|
||||||
else
|
|
||||||
ret = abx500_mask_and_set_register_interruptible(
|
|
||||||
gpadc->dev,
|
|
||||||
AB8500_GPADC,
|
|
||||||
AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write configuration to register */
|
||||||
|
ret = abx500_set_register_interruptible(gpadc->dev,
|
||||||
|
AB8500_GPADC, AB8500_GPADC_CTRL1_REG, val_reg1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(gpadc->dev,
|
dev_err(gpadc->dev,
|
||||||
"gpadc_conversion: select falling edge failed\n");
|
"gpadc_conversion: set Control register failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set trigger delay timer */
|
if (delay_min != 0)
|
||||||
|
usleep_range(delay_min, delay_max);
|
||||||
|
|
||||||
if (conv_type == ADC_HW) {
|
if (conv_type == ADC_HW) {
|
||||||
|
/* Set trigger delay timer */
|
||||||
ret = abx500_set_register_interruptible(gpadc->dev,
|
ret = abx500_set_register_interruptible(gpadc->dev,
|
||||||
AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer);
|
AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, trig_timer);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -556,10 +479,11 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
|
|||||||
"gpadc_conversion: trig timer failed\n");
|
"gpadc_conversion: trig timer failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
completion_timeout = 2 * HZ;
|
||||||
|
data_low_addr = AB8500_GPADC_AUTODATAL_REG;
|
||||||
/* Start SW conversion */
|
data_high_addr = AB8500_GPADC_AUTODATAH_REG;
|
||||||
if (conv_type == ADC_SW) {
|
} else {
|
||||||
|
/* Start SW conversion */
|
||||||
ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
|
ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
|
||||||
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
|
||||||
ADC_SW_CONV, ADC_SW_CONV);
|
ADC_SW_CONV, ADC_SW_CONV);
|
||||||
@ -568,61 +492,35 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
|
|||||||
"gpadc_conversion: start s/w conv failed\n");
|
"gpadc_conversion: start s/w conv failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
completion_timeout = msecs_to_jiffies(CONVERSION_TIME);
|
||||||
|
data_low_addr = AB8500_GPADC_MANDATAL_REG;
|
||||||
|
data_high_addr = AB8500_GPADC_MANDATAH_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for completion of conversion */
|
/* wait for completion of conversion */
|
||||||
if (conv_type == ADC_HW) {
|
if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete,
|
||||||
if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete,
|
completion_timeout)) {
|
||||||
2 * HZ)) {
|
dev_err(gpadc->dev,
|
||||||
dev_err(gpadc->dev,
|
"timeout didn't receive GPADC conv interrupt\n");
|
||||||
"timeout didn't receive hw GPADC conv interrupt\n");
|
ret = -EINVAL;
|
||||||
ret = -EINVAL;
|
goto out;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete,
|
|
||||||
msecs_to_jiffies(CONVERSION_TIME))) {
|
|
||||||
dev_err(gpadc->dev,
|
|
||||||
"timeout didn't receive sw GPADC conv interrupt\n");
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the converted RAW data */
|
/* Read the converted RAW data */
|
||||||
if (conv_type == ADC_HW) {
|
ret = abx500_get_register_interruptible(gpadc->dev,
|
||||||
ret = abx500_get_register_interruptible(gpadc->dev,
|
AB8500_GPADC, data_low_addr, &low_data);
|
||||||
AB8500_GPADC, AB8500_GPADC_AUTODATAL_REG, &low_data);
|
if (ret < 0) {
|
||||||
if (ret < 0) {
|
dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n");
|
||||||
dev_err(gpadc->dev,
|
goto out;
|
||||||
"gpadc_conversion: read hw low data failed\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = abx500_get_register_interruptible(gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_AUTODATAH_REG, &high_data);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(gpadc->dev,
|
|
||||||
"gpadc_conversion: read hw high data failed\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = abx500_get_register_interruptible(gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_MANDATAL_REG, &low_data);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(gpadc->dev,
|
|
||||||
"gpadc_conversion: read sw low data failed\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = abx500_get_register_interruptible(gpadc->dev,
|
|
||||||
AB8500_GPADC, AB8500_GPADC_MANDATAH_REG, &high_data);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(gpadc->dev,
|
|
||||||
"gpadc_conversion: read sw high data failed\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = abx500_get_register_interruptible(gpadc->dev,
|
||||||
|
AB8500_GPADC, data_high_addr, &high_data);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(gpadc->dev, "gpadc_conversion: read high data failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if double convertion is required */
|
/* Check if double convertion is required */
|
||||||
if ((channel == BAT_CTRL_AND_IBAT) ||
|
if ((channel == BAT_CTRL_AND_IBAT) ||
|
||||||
(channel == VBAT_MEAS_AND_IBAT) ||
|
(channel == VBAT_MEAS_AND_IBAT) ||
|
||||||
|
Loading…
Reference in New Issue
Block a user