drivers/clocksource/ingenic-timer.c

Source file repositories/reference/linux-study-clean/drivers/clocksource/ingenic-timer.c

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/ingenic-timer.c
Extension
.c
Size
10696 bytes
Lines
422
Domain
Driver Families
Bucket
drivers/clocksource
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 ingenic_soc_info {
	unsigned int num_channels;
};

struct ingenic_tcu_timer {
	unsigned int cpu;
	unsigned int channel;
	struct clock_event_device cevt;
	struct clk *clk;
	char name[8];
};

struct ingenic_tcu {
	struct regmap *map;
	struct device_node *np;
	struct clk *cs_clk;
	unsigned int cs_channel;
	struct clocksource cs;
	unsigned long pwm_channels_mask;
	struct ingenic_tcu_timer timers[];
};

static struct ingenic_tcu *ingenic_tcu;

static u64 notrace ingenic_tcu_timer_read(void)
{
	struct ingenic_tcu *tcu = ingenic_tcu;
	unsigned int count;

	regmap_read(tcu->map, TCU_REG_TCNTc(tcu->cs_channel), &count);

	return count;
}

static u64 notrace ingenic_tcu_timer_cs_read(struct clocksource *cs)
{
	return ingenic_tcu_timer_read();
}

static inline struct ingenic_tcu *
to_ingenic_tcu(struct ingenic_tcu_timer *timer)
{
	return container_of(timer, struct ingenic_tcu, timers[timer->cpu]);
}

static inline struct ingenic_tcu_timer *
to_ingenic_tcu_timer(struct clock_event_device *evt)
{
	return container_of(evt, struct ingenic_tcu_timer, cevt);
}

static int ingenic_tcu_cevt_set_state_shutdown(struct clock_event_device *evt)
{
	struct ingenic_tcu_timer *timer = to_ingenic_tcu_timer(evt);
	struct ingenic_tcu *tcu = to_ingenic_tcu(timer);

	regmap_write(tcu->map, TCU_REG_TECR, BIT(timer->channel));

	return 0;
}

static int ingenic_tcu_cevt_set_next(unsigned long next,
				     struct clock_event_device *evt)
{
	struct ingenic_tcu_timer *timer = to_ingenic_tcu_timer(evt);
	struct ingenic_tcu *tcu = to_ingenic_tcu(timer);

	if (next > 0xffff)
		return -EINVAL;

	regmap_write(tcu->map, TCU_REG_TDFRc(timer->channel), next);
	regmap_write(tcu->map, TCU_REG_TCNTc(timer->channel), 0);
	regmap_write(tcu->map, TCU_REG_TESR, BIT(timer->channel));

	return 0;
}

static void ingenic_per_cpu_event_handler(void *info)
{
	struct clock_event_device *cevt = (struct clock_event_device *) info;

	cevt->event_handler(cevt);
}

static irqreturn_t ingenic_tcu_cevt_cb(int irq, void *dev_id)
{
	struct ingenic_tcu_timer *timer = dev_id;
	struct ingenic_tcu *tcu = to_ingenic_tcu(timer);
	call_single_data_t *csd;

Annotation

Implementation Notes