static int fsl_pwm_apply_config()

in pwm-fsl-ftm.c [228:298]


static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
				struct pwm_device *pwm,
				const struct pwm_state *newstate)
{
	unsigned int duty;
	u32 reg_polarity;

	struct fsl_pwm_periodcfg periodcfg;
	bool do_write_period = false;

	if (!fsl_pwm_calculate_period(fpc, newstate->period, &periodcfg)) {
		dev_err(fpc->chip.dev, "failed to calculate new period\n");
		return -EINVAL;
	}

	if (!fsl_pwm_is_any_pwm_enabled(fpc, pwm))
		do_write_period = true;
	/*
	 * The Freescale FTM controller supports only a single period for
	 * all PWM channels, therefore verify if the newly computed period
	 * is different than the current period being used. In such case
	 * we allow to change the period only if no other pwm is running.
	 */
	else if (!fsl_pwm_periodcfg_are_equal(&fpc->period, &periodcfg)) {
		if (fsl_pwm_is_other_pwm_enabled(fpc, pwm)) {
			dev_err(fpc->chip.dev,
				"Cannot change period for PWM %u, disable other PWMs first\n",
				pwm->hwpwm);
			return -EBUSY;
		}
		if (fpc->period.clk_select != periodcfg.clk_select) {
			int ret;
			enum fsl_pwm_clk oldclk = fpc->period.clk_select;
			enum fsl_pwm_clk newclk = periodcfg.clk_select;

			ret = clk_prepare_enable(fpc->clk[newclk]);
			if (ret)
				return ret;
			clk_disable_unprepare(fpc->clk[oldclk]);
		}
		do_write_period = true;
	}

	ftm_clear_write_protection(fpc);

	if (do_write_period) {
		regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
				   FTM_SC_CLK(periodcfg.clk_select));
		regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
				   periodcfg.clk_ps);
		regmap_write(fpc->regmap, FTM_MOD, periodcfg.mod_period);

		fpc->period = periodcfg;
	}

	duty = fsl_pwm_calculate_duty(fpc, newstate->duty_cycle);

	regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm),
		     FTM_CSC_MSB | FTM_CSC_ELSB);
	regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty);

	reg_polarity = 0;
	if (newstate->polarity == PWM_POLARITY_INVERSED)
		reg_polarity = BIT(pwm->hwpwm);

	regmap_update_bits(fpc->regmap, FTM_POL, BIT(pwm->hwpwm), reg_polarity);

	ftm_set_write_protection(fpc);

	return 0;
}