in ltc2947-core.c [966:1109]
static int ltc2947_setup(struct ltc2947_data *st)
{
int ret;
struct clk *extclk;
u32 dummy, deadband, pol;
u32 accum[2];
/* clear status register by reading it */
ret = regmap_read(st->map, LTC2947_REG_STATUS, &dummy);
if (ret)
return ret;
/*
* Set max/min for power here since the default values x scale
* would overflow on 32bit arch
*/
ret = ltc2947_val_write(st, LTC2947_REG_POWER_THRE_H, LTC2947_PAGE1, 2,
POWER_MAX / 200000);
if (ret)
return ret;
ret = ltc2947_val_write(st, LTC2947_REG_POWER_THRE_L, LTC2947_PAGE1, 2,
POWER_MIN / 200000);
if (ret)
return ret;
/* check external clock presence */
extclk = devm_clk_get_optional(st->dev, NULL);
if (IS_ERR(extclk))
return dev_err_probe(st->dev, PTR_ERR(extclk),
"Failed to get external clock\n");
if (extclk) {
unsigned long rate_hz;
u8 pre = 0, div, tbctl;
u64 aux;
/* let's calculate and set the right valus in TBCTL */
rate_hz = clk_get_rate(extclk);
if (rate_hz < LTC2947_CLK_MIN || rate_hz > LTC2947_CLK_MAX) {
dev_err(st->dev, "Invalid rate:%lu for external clock",
rate_hz);
return -EINVAL;
}
ret = clk_prepare_enable(extclk);
if (ret)
return ret;
ret = devm_add_action_or_reset(st->dev, ltc2947_clk_disable,
extclk);
if (ret)
return ret;
/* as in table 1 of the datasheet */
if (rate_hz >= LTC2947_CLK_MIN && rate_hz <= 1000000)
pre = 0;
else if (rate_hz > 1000000 && rate_hz <= 2000000)
pre = 1;
else if (rate_hz > 2000000 && rate_hz <= 4000000)
pre = 2;
else if (rate_hz > 4000000 && rate_hz <= 8000000)
pre = 3;
else if (rate_hz > 8000000 && rate_hz <= 16000000)
pre = 4;
else if (rate_hz > 16000000 && rate_hz <= LTC2947_CLK_MAX)
pre = 5;
/*
* Div is given by:
* floor(fref / (2^PRE * 32768))
*/
div = rate_hz / ((1 << pre) * 32768);
tbctl = LTC2947_PRE(pre) | LTC2947_DIV(div);
ret = regmap_write(st->map, LTC2947_REG_TBCTL, tbctl);
if (ret)
return ret;
/*
* The energy lsb is given by (in W*s):
* 06416 * (1/fref) * 2^PRE * (DIV + 1)
* The value is multiplied by 10E9
*/
aux = (div + 1) * ((1 << pre) * 641600000ULL);
st->lsb_energy = DIV_ROUND_CLOSEST_ULL(aux, rate_hz);
} else {
/* 19.89E-6 * 10E9 */
st->lsb_energy = 19890;
}
ret = of_property_read_u32_array(st->dev->of_node,
"adi,accumulator-ctl-pol", accum,
ARRAY_SIZE(accum));
if (!ret) {
u32 accum_reg = LTC2947_ACCUM_POL_1(accum[0]) |
LTC2947_ACCUM_POL_2(accum[1]);
ret = regmap_write(st->map, LTC2947_REG_ACCUM_POL, accum_reg);
if (ret)
return ret;
}
ret = of_property_read_u32(st->dev->of_node,
"adi,accumulation-deadband-microamp",
&deadband);
if (!ret) {
/* the LSB is the same as the current, so 3mA */
ret = regmap_write(st->map, LTC2947_REG_ACCUM_DEADBAND,
deadband / (1000 * 3));
if (ret)
return ret;
}
/* check gpio cfg */
ret = of_property_read_u32(st->dev->of_node, "adi,gpio-out-pol", &pol);
if (!ret) {
/* setup GPIO as output */
u32 gpio_ctl = LTC2947_GPIO_EN(1) | LTC2947_GPIO_FAN_EN(1) |
LTC2947_GPIO_FAN_POL(pol);
st->gpio_out = true;
ret = regmap_write(st->map, LTC2947_REG_GPIOSTATCTL, gpio_ctl);
if (ret)
return ret;
}
ret = of_property_read_u32_array(st->dev->of_node, "adi,gpio-in-accum",
accum, ARRAY_SIZE(accum));
if (!ret) {
/*
* Setup the accum options. The gpioctl is already defined as
* input by default.
*/
u32 accum_val = LTC2947_ACCUM_POL_1(accum[0]) |
LTC2947_ACCUM_POL_2(accum[1]);
if (st->gpio_out) {
dev_err(st->dev,
"Cannot have input gpio config if already configured as output");
return -EINVAL;
}
ret = regmap_write(st->map, LTC2947_REG_GPIO_ACCUM, accum_val);
if (ret)
return ret;
}
/* set continuos mode */
return regmap_update_bits(st->map, LTC2947_REG_CTRL,
LTC2947_CONT_MODE_MASK, LTC2947_CONT_MODE(1));
}