drivers/pwm/pwm-hibvt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pwm/pwm-hibvt.c
Extension
.c
Size
7491 bytes
Lines
286
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 hibvt_pwm_chip {
	struct clk *clk;
	void __iomem *base;
	struct reset_control *rstc;
	const struct hibvt_pwm_soc *soc;
};

struct hibvt_pwm_soc {
	u32 num_pwms;
	bool quirk_force_enable;
};

static const struct hibvt_pwm_soc hi3516cv300_soc_info = {
	.num_pwms = 4,
};

static const struct hibvt_pwm_soc hi3519v100_soc_info = {
	.num_pwms = 8,
};

static const struct hibvt_pwm_soc hi3559v100_shub_soc_info = {
	.num_pwms = 8,
	.quirk_force_enable = true,
};

static const struct hibvt_pwm_soc hi3559v100_soc_info = {
	.num_pwms = 2,
	.quirk_force_enable = true,
};

static inline struct hibvt_pwm_chip *to_hibvt_pwm_chip(struct pwm_chip *chip)
{
	return pwmchip_get_drvdata(chip);
}

static void hibvt_pwm_set_bits(void __iomem *base, u32 offset,
					u32 mask, u32 data)
{
	void __iomem *address = base + offset;
	u32 value;

	value = readl(address);
	value &= ~mask;
	value |= (data & mask);
	writel(value, address);
}

static void hibvt_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);

	hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
			PWM_ENABLE_MASK, 0x1);
}

static void hibvt_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);

	hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
			PWM_ENABLE_MASK, 0x0);
}

static void hibvt_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
					int duty_cycle_ns, int period_ns)
{
	struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);
	u32 freq, period, duty;

	freq = div_u64(clk_get_rate(hi_pwm_chip->clk), 1000000);

	period = div_u64(freq * period_ns, 1000);
	duty = div_u64(period * duty_cycle_ns, period_ns);

	hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CFG0_ADDR(pwm->hwpwm),
			PWM_PERIOD_MASK, period);

	hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CFG1_ADDR(pwm->hwpwm),
			PWM_DUTY_MASK, duty);
}

static void hibvt_pwm_set_polarity(struct pwm_chip *chip,
					struct pwm_device *pwm,
					enum pwm_polarity polarity)
{
	struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);

	if (polarity == PWM_POLARITY_INVERSED)
		hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
				PWM_POLARITY_MASK, (0x1 << PWM_POLARITY_SHIFT));

Annotation

Implementation Notes