drivers/pwm/pwm-renesas-tpu.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pwm/pwm-renesas-tpu.c
Extension
.c
Size
12489 bytes
Lines
506
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 tpu_pwm_device {
	bool timer_on;			/* Whether the timer is running */

	struct tpu_device *tpu;
	unsigned int channel;		/* Channel number in the TPU */

	enum pwm_polarity polarity;
	unsigned int prescaler;
	u16 period;
	u16 duty;
};

struct tpu_device {
	struct platform_device *pdev;
	spinlock_t lock;

	void __iomem *base;
	struct clk *clk;
	struct tpu_pwm_device tpd[TPU_CHANNEL_MAX];
};

static inline struct tpu_device *to_tpu_device(struct pwm_chip *chip)
{
	return pwmchip_get_drvdata(chip);
}

static void tpu_pwm_write(struct tpu_pwm_device *tpd, int reg_nr, u16 value)
{
	void __iomem *base = tpd->tpu->base + TPU_CHANNEL_OFFSET
			   + tpd->channel * TPU_CHANNEL_SIZE;

	iowrite16(value, base + reg_nr);
}

static void tpu_pwm_set_pin(struct tpu_pwm_device *tpd,
			    enum tpu_pin_state state)
{
	static const char * const states[] = { "inactive", "PWM", "active" };

	dev_dbg(&tpd->tpu->pdev->dev, "%u: configuring pin as %s\n",
		tpd->channel, states[state]);

	switch (state) {
	case TPU_PIN_INACTIVE:
		tpu_pwm_write(tpd, TPU_TIORn,
			      tpd->polarity == PWM_POLARITY_INVERSED ?
			      TPU_TIOR_IOA_1 : TPU_TIOR_IOA_0);
		break;
	case TPU_PIN_PWM:
		tpu_pwm_write(tpd, TPU_TIORn,
			      tpd->polarity == PWM_POLARITY_INVERSED ?
			      TPU_TIOR_IOA_0_SET : TPU_TIOR_IOA_1_CLR);
		break;
	case TPU_PIN_ACTIVE:
		tpu_pwm_write(tpd, TPU_TIORn,
			      tpd->polarity == PWM_POLARITY_INVERSED ?
			      TPU_TIOR_IOA_0 : TPU_TIOR_IOA_1);
		break;
	}
}

static void tpu_pwm_start_stop(struct tpu_pwm_device *tpd, int start)
{
	unsigned long flags;
	u16 value;

	spin_lock_irqsave(&tpd->tpu->lock, flags);
	value = ioread16(tpd->tpu->base + TPU_TSTR);

	if (start)
		value |= 1 << tpd->channel;
	else
		value &= ~(1 << tpd->channel);

	iowrite16(value, tpd->tpu->base + TPU_TSTR);
	spin_unlock_irqrestore(&tpd->tpu->lock, flags);
}

static int tpu_pwm_timer_start(struct tpu_pwm_device *tpd)
{
	int ret;

	if (!tpd->timer_on) {
		/* Wake up device and enable clock. */
		pm_runtime_get_sync(&tpd->tpu->pdev->dev);
		ret = clk_prepare_enable(tpd->tpu->clk);
		if (ret) {
			dev_err(&tpd->tpu->pdev->dev, "cannot enable clock\n");
			return ret;
		}

Annotation

Implementation Notes