static int ltc2947_setup()

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));
}