drivers/rtc/rtc-gamecube.c

Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-gamecube.c

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-gamecube.c
Extension
.c
Size
10490 bytes
Lines
383
Domain
Driver Families
Bucket
drivers/rtc
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 priv {
	struct regmap *regmap;
	void __iomem *iob;
	u32 rtc_bias;
};

static int exi_read(void *context, u32 reg, u32 *data)
{
	struct priv *d = (struct priv *)context;
	void __iomem *iob = d->iob;

	/* The spin loops here loop about 15~16 times each, so there is no need
	 * to use a more expensive sleep method.
	 */

	/* Write register offset */
	iowrite32be(RTC_EXICSR, iob + EXICSR);
	iowrite32be(reg << 8, iob + EXIDATA);
	iowrite32be(RTC_EXICR_W, iob + EXICR);
	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
		cpu_relax();

	/* Read data */
	iowrite32be(RTC_EXICSR, iob + EXICSR);
	iowrite32be(RTC_EXICR_R, iob + EXICR);
	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
		cpu_relax();
	*data = ioread32be(iob + EXIDATA);

	/* Clear channel parameters */
	iowrite32be(0, iob + EXICSR);

	return 0;
}

static int exi_write(void *context, u32 reg, u32 data)
{
	struct priv *d = (struct priv *)context;
	void __iomem *iob = d->iob;

	/* The spin loops here loop about 15~16 times each, so there is no need
	 * to use a more expensive sleep method.
	 */

	/* Write register offset */
	iowrite32be(RTC_EXICSR, iob + EXICSR);
	iowrite32be(RTC_EXIDATA_W | (reg << 8), iob + EXIDATA);
	iowrite32be(RTC_EXICR_W, iob + EXICR);
	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
		cpu_relax();

	/* Write data */
	iowrite32be(RTC_EXICSR, iob + EXICSR);
	iowrite32be(data, iob + EXIDATA);
	iowrite32be(RTC_EXICR_W, iob + EXICR);
	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
		cpu_relax();

	/* Clear channel parameters */
	iowrite32be(0, iob + EXICSR);

	return 0;
}

static const struct regmap_bus exi_bus = {
	/* TODO: is that true?  Not that it matters here, but still. */
	.fast_io = true,
	.reg_read = exi_read,
	.reg_write = exi_write,
};

static int gamecube_rtc_read_time(struct device *dev, struct rtc_time *t)
{
	struct priv *d = dev_get_drvdata(dev);
	int ret;
	u32 counter;
	time64_t timestamp;

	ret = regmap_read(d->regmap, RTC_COUNTER, &counter);
	if (ret)
		return ret;

	/* Add the counter and the bias to obtain the timestamp */
	timestamp = (time64_t)d->rtc_bias + counter;
	rtc_time64_to_tm(timestamp, t);

	return 0;
}

static int gamecube_rtc_set_time(struct device *dev, struct rtc_time *t)

Annotation

Implementation Notes