drivers/counter/ftm-quaddec.c

Source file repositories/reference/linux-study-clean/drivers/counter/ftm-quaddec.c

File Facts

System
Linux kernel
Corpus path
drivers/counter/ftm-quaddec.c
Extension
.c
Size
8308 bytes
Lines
331
Domain
Driver Families
Bucket
drivers/counter
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 ftm_quaddec {
	struct platform_device *pdev;
	void __iomem *ftm_base;
	bool big_endian;
	struct mutex ftm_quaddec_mutex;
};

static void ftm_read(struct ftm_quaddec *ftm, uint32_t offset, uint32_t *data)
{
	if (ftm->big_endian)
		*data = ioread32be(ftm->ftm_base + offset);
	else
		*data = ioread32(ftm->ftm_base + offset);
}

static void ftm_write(struct ftm_quaddec *ftm, uint32_t offset, uint32_t data)
{
	if (ftm->big_endian)
		iowrite32be(data, ftm->ftm_base + offset);
	else
		iowrite32(data, ftm->ftm_base + offset);
}

/* Hold mutex before modifying write protection state */
static void ftm_clear_write_protection(struct ftm_quaddec *ftm)
{
	uint32_t flag;

	/* First see if it is enabled */
	ftm_read(ftm, FTM_FMS, &flag);

	if (flag & FTM_FMS_WPEN)
		FTM_FIELD_UPDATE(ftm, FTM_MODE, FTM_MODE_WPDIS, 1);
}

static void ftm_set_write_protection(struct ftm_quaddec *ftm)
{
	FTM_FIELD_UPDATE(ftm, FTM_FMS, FTM_FMS_WPEN, 1);
}

static void ftm_reset_counter(struct ftm_quaddec *ftm)
{
	/* Reset hardware counter to CNTIN */
	ftm_write(ftm, FTM_CNT, 0x0);
}

static void ftm_quaddec_init(struct ftm_quaddec *ftm)
{
	ftm_clear_write_protection(ftm);

	/*
	 * Do not write in the region from the CNTIN register through the
	 * PWMLOAD register when FTMEN = 0.
	 * Also reset other fields to zero
	 */
	ftm_write(ftm, FTM_MODE, FTM_MODE_FTMEN);
	ftm_write(ftm, FTM_CNTIN, 0x0000);
	ftm_write(ftm, FTM_MOD, 0xffff);
	ftm_write(ftm, FTM_CNT, 0x0);
	/* Set prescaler, reset other fields to zero */
	ftm_write(ftm, FTM_SC, FTM_SC_PS_1);

	/* Select quad mode, reset other fields to zero */
	ftm_write(ftm, FTM_QDCTRL, FTM_QDCTRL_QUADEN);

	/* Unused features and reset to default section */
	ftm_write(ftm, FTM_POL, 0x0);
	ftm_write(ftm, FTM_FLTCTRL, 0x0);
	ftm_write(ftm, FTM_SYNCONF, 0x0);
	ftm_write(ftm, FTM_SYNC, 0xffff);

	/* Lock the FTM */
	ftm_set_write_protection(ftm);
}

static void ftm_quaddec_disable(void *ftm)
{
	struct ftm_quaddec *ftm_qua = ftm;

	ftm_clear_write_protection(ftm_qua);
	ftm_write(ftm_qua, FTM_MODE, 0);
	ftm_write(ftm_qua, FTM_QDCTRL, 0);
	/*
	 * This is enough to disable the counter. No clock has been
	 * selected by writing to FTM_SC in init()
	 */
	ftm_set_write_protection(ftm_qua);
}

static int ftm_quaddec_get_prescaler(struct counter_device *counter,

Annotation

Implementation Notes