drivers/pwm/pwm-fsl-ftm.c

Source file repositories/reference/linux-study-clean/drivers/pwm/pwm-fsl-ftm.c

File Facts

System
Linux kernel
Corpus path
drivers/pwm/pwm-fsl-ftm.c
Extension
.c
Size
13526 bytes
Lines
573
Domain
Driver Families
Bucket
drivers/pwm
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct fsl_ftm_soc {
	bool has_enable_bits;
	bool has_flt_reg;
	unsigned int npwm;
};

struct fsl_pwm_periodcfg {
	enum fsl_pwm_clk clk_select;
	unsigned int clk_ps;
	unsigned int mod_period;
};

struct fsl_pwm_chip {
	struct regmap *regmap;

	/* This value is valid iff a pwm is running */
	struct fsl_pwm_periodcfg period;

	struct clk *ipg_clk;
	struct clk *clk[FSL_PWM_CLK_MAX];

	const struct fsl_ftm_soc *soc;
};

static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
{
	return pwmchip_get_drvdata(chip);
}

static void ftm_clear_write_protection(struct fsl_pwm_chip *fpc)
{
	u32 val;

	regmap_read(fpc->regmap, FTM_FMS, &val);
	if (val & FTM_FMS_WPEN)
		regmap_set_bits(fpc->regmap, FTM_MODE, FTM_MODE_WPDIS);
}

static void ftm_set_write_protection(struct fsl_pwm_chip *fpc)
{
	regmap_set_bits(fpc->regmap, FTM_FMS, FTM_FMS_WPEN);
}

static bool fsl_pwm_periodcfg_are_equal(const struct fsl_pwm_periodcfg *a,
					const struct fsl_pwm_periodcfg *b)
{
	if (a->clk_select != b->clk_select)
		return false;
	if (a->clk_ps != b->clk_ps)
		return false;
	if (a->mod_period != b->mod_period)
		return false;
	return true;
}

static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
	int ret;
	struct fsl_pwm_chip *fpc = to_fsl_chip(chip);

	ret = clk_prepare_enable(fpc->ipg_clk);
	if (!ret && fpc->soc->has_enable_bits)
		regmap_set_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16));

	return ret;
}

static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct fsl_pwm_chip *fpc = to_fsl_chip(chip);

	if (fpc->soc->has_enable_bits)
		regmap_clear_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16));

	clk_disable_unprepare(fpc->ipg_clk);
}

static unsigned int fsl_pwm_ticks_to_ns(struct fsl_pwm_chip *fpc,
					  unsigned int ticks)
{
	unsigned long rate;
	unsigned long long exval;

	rate = clk_get_rate(fpc->clk[fpc->period.clk_select]);
	if (rate >> fpc->period.clk_ps == 0)
		return 0;

	exval = ticks;
	exval *= 1000000000UL;
	do_div(exval, rate >> fpc->period.clk_ps);

Annotation

Implementation Notes