REGULATOR: Move functions for handling with regulator ranges to
common file. They can be useful for other PMICs. MFC after: 2 weeks
This commit is contained in:
parent
4d517b66a0
commit
fd02931841
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=307558
@ -71,13 +71,6 @@ enum as3722_reg_id {
|
||||
AS3722_REG_ID_LDO11,
|
||||
};
|
||||
|
||||
struct regulator_range {
|
||||
u_int min_uvolt;
|
||||
u_int step_uvolt;
|
||||
u_int min_sel;
|
||||
u_int max_sel;
|
||||
};
|
||||
|
||||
|
||||
/* Regulator HW definition. */
|
||||
struct reg_def {
|
||||
@ -107,40 +100,32 @@ struct as3722_reg_sc {
|
||||
int enable_usec;
|
||||
};
|
||||
|
||||
#define RANGE_INIT(_min_sel, _max_sel, _min_uvolt, _step_uvolt) \
|
||||
{ \
|
||||
.min_sel = _min_sel, \
|
||||
.max_sel = _max_sel, \
|
||||
.min_uvolt = _min_uvolt, \
|
||||
.step_uvolt = _step_uvolt, \
|
||||
}
|
||||
|
||||
static struct regulator_range as3722_sd016_ranges[] = {
|
||||
RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
RANGE_INIT(0x01, 0x5A, 610000, 10000),
|
||||
REG_RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
REG_RANGE_INIT(0x01, 0x5A, 610000, 10000),
|
||||
};
|
||||
|
||||
static struct regulator_range as3722_sd0_lv_ranges[] = {
|
||||
RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
RANGE_INIT(0x01, 0x6E, 410000, 10000),
|
||||
REG_RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
REG_RANGE_INIT(0x01, 0x6E, 410000, 10000),
|
||||
};
|
||||
|
||||
static struct regulator_range as3722_sd_ranges[] = {
|
||||
RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
RANGE_INIT(0x01, 0x40, 612500, 12500),
|
||||
RANGE_INIT(0x41, 0x70, 1425000, 25000),
|
||||
RANGE_INIT(0x71, 0x7F, 2650000, 50000),
|
||||
REG_RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
REG_RANGE_INIT(0x01, 0x40, 612500, 12500),
|
||||
REG_RANGE_INIT(0x41, 0x70, 1425000, 25000),
|
||||
REG_RANGE_INIT(0x71, 0x7F, 2650000, 50000),
|
||||
};
|
||||
|
||||
static struct regulator_range as3722_ldo3_ranges[] = {
|
||||
RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
RANGE_INIT(0x01, 0x2D, 620000, 20000),
|
||||
REG_RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
REG_RANGE_INIT(0x01, 0x2D, 620000, 20000),
|
||||
};
|
||||
|
||||
static struct regulator_range as3722_ldo_ranges[] = {
|
||||
RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
RANGE_INIT(0x01, 0x24, 825000, 25000),
|
||||
RANGE_INIT(0x40, 0x7F, 1725000, 25000),
|
||||
REG_RANGE_INIT(0x00, 0x00, 0, 0),
|
||||
REG_RANGE_INIT(0x01, 0x24, 825000, 25000),
|
||||
REG_RANGE_INIT(0x40, 0x7F, 1725000, 25000),
|
||||
};
|
||||
|
||||
static struct reg_def as3722s_def[] = {
|
||||
@ -401,87 +386,6 @@ static regnode_method_t as3722_regnode_methods[] = {
|
||||
DEFINE_CLASS_1(as3722_regnode, as3722_regnode_class, as3722_regnode_methods,
|
||||
sizeof(struct as3722_reg_sc), regnode_class);
|
||||
|
||||
static int
|
||||
regulator_range_sel_to_volt(struct as3722_reg_sc *sc, uint8_t sel, int *volt)
|
||||
{
|
||||
struct regulator_range *range;
|
||||
struct reg_def *def;
|
||||
int i;
|
||||
|
||||
def = sc->def;
|
||||
if (def->nranges == 0)
|
||||
panic("Voltage regulator have zero ranges\n");
|
||||
|
||||
for (i = 0; i < def->nranges ; i++) {
|
||||
range = def->ranges + i;
|
||||
|
||||
if (!(sel >= range->min_sel &&
|
||||
sel <= range->max_sel))
|
||||
continue;
|
||||
|
||||
sel -= range->min_sel;
|
||||
|
||||
*volt = range->min_uvolt + sel * range->step_uvolt;
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (ERANGE);
|
||||
}
|
||||
|
||||
static int
|
||||
regulator_range_volt_to_sel(struct as3722_reg_sc *sc, int min_uvolt,
|
||||
int max_uvolt, uint8_t *out_sel)
|
||||
{
|
||||
struct regulator_range *range;
|
||||
struct reg_def *def;
|
||||
uint8_t sel;
|
||||
int uvolt;
|
||||
int rv, i;
|
||||
|
||||
def = sc->def;
|
||||
if (def->nranges == 0)
|
||||
panic("Voltage regulator have zero ranges\n");
|
||||
|
||||
for (i = 0; i < def->nranges; i++) {
|
||||
range = def->ranges + i;
|
||||
uvolt = range->min_uvolt +
|
||||
(range->max_sel - range->min_sel) * range->step_uvolt;
|
||||
|
||||
if ((min_uvolt > uvolt) ||
|
||||
(max_uvolt < range->min_uvolt))
|
||||
continue;
|
||||
|
||||
if (min_uvolt <= range->min_uvolt)
|
||||
min_uvolt = range->min_uvolt;
|
||||
|
||||
/* If step is zero then range is fixed voltage range. */
|
||||
if (range->step_uvolt == 0)
|
||||
sel = 0;
|
||||
else
|
||||
sel = DIV_ROUND_UP(min_uvolt - range->min_uvolt,
|
||||
range->step_uvolt);
|
||||
|
||||
|
||||
sel += range->min_sel;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= def->nranges)
|
||||
return (ERANGE);
|
||||
|
||||
/* Verify new settings. */
|
||||
rv = regulator_range_sel_to_volt(sc, sel, &uvolt);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
if ((uvolt < min_uvolt) || (uvolt > max_uvolt))
|
||||
return (ERANGE);
|
||||
|
||||
*out_sel = sel;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
as3722_read_sel(struct as3722_reg_sc *sc, uint8_t *sel)
|
||||
{
|
||||
@ -783,7 +687,8 @@ as3722_regnode_set_volt(struct regnode *regnode, int min_uvolt, int max_uvolt,
|
||||
sc = regnode_get_softc(regnode);
|
||||
|
||||
*udelay = 0;
|
||||
rv = regulator_range_volt_to_sel(sc, min_uvolt, max_uvolt, &sel);
|
||||
rv = regulator_range_volt_to_sel8(sc->def->ranges, sc->def->nranges,
|
||||
min_uvolt, max_uvolt, &sel);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
rv = as3722_write_sel(sc, sel);
|
||||
@ -806,6 +711,7 @@ as3722_regnode_get_volt(struct regnode *regnode, int *uvolt)
|
||||
/* LDO6 have bypass. */
|
||||
if (sc->def->id == AS3722_REG_ID_LDO6 && sel == AS3722_LDO6_SEL_BYPASS)
|
||||
return (ENOENT);
|
||||
rv = regulator_range_sel_to_volt(sc, sel, uvolt);
|
||||
rv = regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges,
|
||||
sel, uvolt);
|
||||
return (rv);
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
MALLOC_DEFINE(M_REGULATOR, "regulator", "Regulator framework");
|
||||
|
||||
#define DIV_ROUND_UP(n,d) howmany(n, d)
|
||||
|
||||
/* Forward declarations. */
|
||||
struct regulator;
|
||||
struct regnode;
|
||||
@ -984,3 +986,87 @@ regulator_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name,
|
||||
return (regulator_get_by_id(cdev, regdev, id, reg));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
*
|
||||
* Regulator utility functions.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Convert raw selector value to real voltage */
|
||||
int
|
||||
regulator_range_sel8_to_volt(struct regulator_range *ranges, int nranges,
|
||||
uint8_t sel, int *volt)
|
||||
{
|
||||
struct regulator_range *range;
|
||||
int i;
|
||||
|
||||
if (nranges == 0)
|
||||
panic("Voltage regulator have zero ranges\n");
|
||||
|
||||
for (i = 0; i < nranges ; i++) {
|
||||
range = ranges + i;
|
||||
|
||||
if (!(sel >= range->min_sel &&
|
||||
sel <= range->max_sel))
|
||||
continue;
|
||||
|
||||
sel -= range->min_sel;
|
||||
|
||||
*volt = range->min_uvolt + sel * range->step_uvolt;
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (ERANGE);
|
||||
}
|
||||
|
||||
int
|
||||
regulator_range_volt_to_sel8(struct regulator_range *ranges, int nranges,
|
||||
int min_uvolt, int max_uvolt, uint8_t *out_sel)
|
||||
{
|
||||
struct regulator_range *range;
|
||||
uint8_t sel;
|
||||
int uvolt;
|
||||
int rv, i;
|
||||
|
||||
if (nranges == 0)
|
||||
panic("Voltage regulator have zero ranges\n");
|
||||
|
||||
for (i = 0; i < nranges; i++) {
|
||||
range = ranges + i;
|
||||
uvolt = range->min_uvolt +
|
||||
(range->max_sel - range->min_sel) * range->step_uvolt;
|
||||
|
||||
if ((min_uvolt > uvolt) ||
|
||||
(max_uvolt < range->min_uvolt))
|
||||
continue;
|
||||
|
||||
if (min_uvolt <= range->min_uvolt)
|
||||
min_uvolt = range->min_uvolt;
|
||||
|
||||
/* if step == 0 -> fixed voltage range. */
|
||||
if (range->step_uvolt == 0)
|
||||
sel = 0;
|
||||
else
|
||||
sel = DIV_ROUND_UP(min_uvolt - range->min_uvolt,
|
||||
range->step_uvolt);
|
||||
|
||||
|
||||
sel += range->min_sel;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= nranges)
|
||||
return (ERANGE);
|
||||
|
||||
/* Verify new settings. */
|
||||
rv = regulator_range_sel8_to_volt(ranges, nranges, sel, &uvolt);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
if ((uvolt < min_uvolt) || (uvolt > max_uvolt))
|
||||
return (ERANGE);
|
||||
|
||||
*out_sel = sel;
|
||||
return (0);
|
||||
}
|
||||
|
@ -67,9 +67,22 @@ struct regnode_init_def {
|
||||
#ifdef FDT
|
||||
phandle_t ofw_node; /* OFW node of regulator */
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct regulator_range {
|
||||
int min_uvolt;
|
||||
int step_uvolt;
|
||||
uint8_t min_sel;
|
||||
uint8_t max_sel;
|
||||
};
|
||||
|
||||
#define REG_RANGE_INIT(_min_sel, _max_sel, _min_uvolt, _step_uvolt) { \
|
||||
.min_sel = _min_sel, \
|
||||
.max_sel = _max_sel, \
|
||||
.min_uvolt = _min_uvolt, \
|
||||
.step_uvolt = _step_uvolt, \
|
||||
}
|
||||
|
||||
/*
|
||||
* Shorthands for constructing method tables.
|
||||
*/
|
||||
@ -125,4 +138,10 @@ int regulator_parse_ofw_stdparam(device_t dev, phandle_t node,
|
||||
struct regnode_init_def *def);
|
||||
#endif
|
||||
|
||||
/* Utility functions */
|
||||
int regulator_range_volt_to_sel8(struct regulator_range *ranges, int nranges,
|
||||
int min_uvolt, int max_uvolt, uint8_t *out_sel);
|
||||
int regulator_range_sel8_to_volt(struct regulator_range *ranges, int nranges,
|
||||
uint8_t sel, int *volt);
|
||||
|
||||
#endif /* _DEV_EXTRES_REGULATOR_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user