mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
power: supply: bd70528: use linear ranges
Change the bd70528 to use common linear_range code instead of implementing a copy of it in this driver. Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
This commit is contained in:
parent
bf584e4dbd
commit
92f7d90972
2 changed files with 56 additions and 89 deletions
|
@ -706,6 +706,7 @@ config CHARGER_UCS1002
|
||||||
config CHARGER_BD70528
|
config CHARGER_BD70528
|
||||||
tristate "ROHM bd70528 charger driver"
|
tristate "ROHM bd70528 charger driver"
|
||||||
depends on MFD_ROHM_BD70528
|
depends on MFD_ROHM_BD70528
|
||||||
|
select LINEAR_RANGES
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Say Y here to enable support for getting battery status
|
Say Y here to enable support for getting battery status
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/power_supply.h>
|
#include <linux/power_supply.h>
|
||||||
|
#include <linux/linear_range.h>
|
||||||
|
|
||||||
#define CHG_STAT_SUSPEND 0x0
|
#define CHG_STAT_SUSPEND 0x0
|
||||||
#define CHG_STAT_TRICKLE 0x1
|
#define CHG_STAT_TRICKLE 0x1
|
||||||
|
@ -335,38 +336,37 @@ static int bd70528_get_present(struct bd70528_psy *bdpsy, int *val)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bd70528_linear_range {
|
static const struct linear_range current_limit_ranges[] = {
|
||||||
int min;
|
|
||||||
int step;
|
|
||||||
int vals;
|
|
||||||
int low_sel;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct bd70528_linear_range current_limit_ranges[] = {
|
|
||||||
{
|
{
|
||||||
.min = 5,
|
.min = 5,
|
||||||
.step = 1,
|
.step = 1,
|
||||||
.vals = 36,
|
.min_sel = 0,
|
||||||
.low_sel = 0,
|
.max_sel = 0x22,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.min = 40,
|
.min = 40,
|
||||||
.step = 5,
|
.step = 5,
|
||||||
.vals = 5,
|
.min_sel = 0x23,
|
||||||
.low_sel = 0x23,
|
.max_sel = 0x26,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.min = 60,
|
.min = 60,
|
||||||
.step = 20,
|
.step = 20,
|
||||||
.vals = 8,
|
.min_sel = 0x27,
|
||||||
.low_sel = 0x27,
|
.max_sel = 0x2d,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.min = 200,
|
.min = 200,
|
||||||
.step = 50,
|
.step = 50,
|
||||||
.vals = 7,
|
.min_sel = 0x2e,
|
||||||
.low_sel = 0x2e,
|
.max_sel = 0x34,
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
.min = 500,
|
||||||
|
.step = 0,
|
||||||
|
.min_sel = 0x35,
|
||||||
|
.max_sel = 0x3f,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -374,18 +374,18 @@ static const struct bd70528_linear_range current_limit_ranges[] = {
|
||||||
* voltage for low temperatures. The driver currently only reads
|
* voltage for low temperatures. The driver currently only reads
|
||||||
* the charge current at room temperature. We do set both though.
|
* the charge current at room temperature. We do set both though.
|
||||||
*/
|
*/
|
||||||
static const struct bd70528_linear_range warm_charge_curr[] = {
|
static const struct linear_range warm_charge_curr[] = {
|
||||||
{
|
{
|
||||||
.min = 10,
|
.min = 10,
|
||||||
.step = 10,
|
.step = 10,
|
||||||
.vals = 20,
|
.min_sel = 0,
|
||||||
.low_sel = 0,
|
.max_sel = 0x12,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.min = 200,
|
.min = 200,
|
||||||
.step = 25,
|
.step = 25,
|
||||||
.vals = 13,
|
.min_sel = 0x13,
|
||||||
.low_sel = 0x13,
|
.max_sel = 0x1f,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -398,56 +398,6 @@ static const struct bd70528_linear_range warm_charge_curr[] = {
|
||||||
#define MAX_WARM_CHG_CURR_SEL 0x1f
|
#define MAX_WARM_CHG_CURR_SEL 0x1f
|
||||||
#define MIN_CHG_CURR_SEL 0x0
|
#define MIN_CHG_CURR_SEL 0x0
|
||||||
|
|
||||||
static int find_value_for_selector_low(const struct bd70528_linear_range *r,
|
|
||||||
int selectors, unsigned int sel,
|
|
||||||
unsigned int *val)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < selectors; i++) {
|
|
||||||
if (r[i].low_sel <= sel && r[i].low_sel + r[i].vals >= sel) {
|
|
||||||
*val = r[i].min + (sel - r[i].low_sel) * r[i].step;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For BD70528 voltage/current limits we happily accept any value which
|
|
||||||
* belongs the range. We could check if value matching the selector is
|
|
||||||
* desired by computing the range min + (sel - sel_low) * range step - but
|
|
||||||
* I guess it is enough if we use voltage/current which is closest (below)
|
|
||||||
* the requested?
|
|
||||||
*/
|
|
||||||
static int find_selector_for_value_low(const struct bd70528_linear_range *r,
|
|
||||||
int selectors, unsigned int val,
|
|
||||||
unsigned int *sel, bool *found)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
*found = false;
|
|
||||||
for (i = 0; i < selectors; i++) {
|
|
||||||
if (r[i].min <= val) {
|
|
||||||
if (r[i].min + r[i].step * r[i].vals >= val) {
|
|
||||||
*found = true;
|
|
||||||
*sel = r[i].low_sel + (val - r[i].min) /
|
|
||||||
r[i].step;
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If the range max is smaller than requested
|
|
||||||
* we can set the max supported value from range
|
|
||||||
*/
|
|
||||||
*sel = r[i].low_sel + r[i].vals;
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_charge_current(struct bd70528_psy *bdpsy, int *ma)
|
static int get_charge_current(struct bd70528_psy *bdpsy, int *ma)
|
||||||
{
|
{
|
||||||
unsigned int sel;
|
unsigned int sel;
|
||||||
|
@ -463,9 +413,9 @@ static int get_charge_current(struct bd70528_psy *bdpsy, int *ma)
|
||||||
|
|
||||||
sel &= BD70528_MASK_CHG_CHG_CURR;
|
sel &= BD70528_MASK_CHG_CHG_CURR;
|
||||||
|
|
||||||
ret = find_value_for_selector_low(&warm_charge_curr[0],
|
ret = linear_range_get_value_array(&warm_charge_curr[0],
|
||||||
ARRAY_SIZE(warm_charge_curr), sel,
|
ARRAY_SIZE(warm_charge_curr),
|
||||||
ma);
|
sel, ma);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(bdpsy->dev,
|
dev_err(bdpsy->dev,
|
||||||
"Unknown charge current value 0x%x\n",
|
"Unknown charge current value 0x%x\n",
|
||||||
|
@ -491,10 +441,9 @@ static int get_current_limit(struct bd70528_psy *bdpsy, int *ma)
|
||||||
|
|
||||||
sel &= BD70528_MASK_CHG_DCIN_ILIM;
|
sel &= BD70528_MASK_CHG_DCIN_ILIM;
|
||||||
|
|
||||||
ret = find_value_for_selector_low(¤t_limit_ranges[0],
|
ret = linear_range_get_value_array(¤t_limit_ranges[0],
|
||||||
ARRAY_SIZE(current_limit_ranges), sel,
|
ARRAY_SIZE(current_limit_ranges),
|
||||||
ma);
|
sel, ma);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Unspecified values mean 500 mA */
|
/* Unspecified values mean 500 mA */
|
||||||
*ma = 500;
|
*ma = 500;
|
||||||
|
@ -588,15 +537,28 @@ static int set_charge_current(struct bd70528_psy *bdpsy, int ma)
|
||||||
goto set;
|
goto set;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = find_selector_for_value_low(&warm_charge_curr[0],
|
/*
|
||||||
ARRAY_SIZE(warm_charge_curr), ma,
|
* For BD70528 voltage/current limits we happily accept any value which
|
||||||
®, &found);
|
* belongs the range. We could check if value matching the selector is
|
||||||
|
* desired by computing the range min + (sel - sel_low) * range step - but
|
||||||
|
* I guess it is enough if we use voltage/current which is closest (below)
|
||||||
|
* the requested?
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = linear_range_get_selector_low_array(warm_charge_curr,
|
||||||
|
ARRAY_SIZE(warm_charge_curr),
|
||||||
|
ma, ®, &found);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
dev_err(bdpsy->dev,
|
||||||
|
"Unsupported charge current %u mA\n", ma);
|
||||||
reg = MIN_CHG_CURR_SEL;
|
reg = MIN_CHG_CURR_SEL;
|
||||||
goto set;
|
goto set;
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
/* There was a gap in supported values and we hit it */
|
/*
|
||||||
|
* There was a gap in supported values and we hit it.
|
||||||
|
* Yet a smaller value was found so we use it.
|
||||||
|
*/
|
||||||
dev_warn(bdpsy->dev,
|
dev_warn(bdpsy->dev,
|
||||||
"Unsupported charge current %u mA\n", ma);
|
"Unsupported charge current %u mA\n", ma);
|
||||||
}
|
}
|
||||||
|
@ -648,17 +610,21 @@ static int set_current_limit(struct bd70528_psy *bdpsy, int ma)
|
||||||
goto set;
|
goto set;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = find_selector_for_value_low(¤t_limit_ranges[0],
|
ret = linear_range_get_selector_low_array(current_limit_ranges,
|
||||||
ARRAY_SIZE(current_limit_ranges), ma,
|
ARRAY_SIZE(current_limit_ranges),
|
||||||
®, &found);
|
ma, ®, &found);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
dev_err(bdpsy->dev, "Unsupported current limit %umA\n", ma);
|
||||||
reg = MIN_CURR_LIMIT_SEL;
|
reg = MIN_CURR_LIMIT_SEL;
|
||||||
goto set;
|
goto set;
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
/* There was a gap in supported values and we hit it ?*/
|
/*
|
||||||
dev_warn(bdpsy->dev, "Unsupported current limit %umA\n",
|
* There was a gap in supported values and we hit it.
|
||||||
ma);
|
* We found a smaller value from ranges and use it.
|
||||||
|
* Warn user though.
|
||||||
|
*/
|
||||||
|
dev_warn(bdpsy->dev, "Unsupported current limit %umA\n", ma);
|
||||||
}
|
}
|
||||||
|
|
||||||
set:
|
set:
|
||||||
|
|
Loading…
Reference in a new issue