drivers/rtc/rtc-ssd202d.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-ssd202d.c
Extension
.c
Size
6361 bytes
Lines
250
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 ssd202d_rtc {
	struct rtc_device *rtc_dev;
	void __iomem *base;
};

static u8 read_iso_en(void __iomem *base)
{
	return readb(base + REG_RTC_TEST) & 0x1;
}

static u8 read_iso_ctrl_ack(void __iomem *base)
{
	return (readb(base + REG_ISOACK) & ISO_CTRL_ACK_MASK) >> ISO_CTRL_ACK_SHIFT;
}

static int ssd202d_rtc_isoctrl(struct ssd202d_rtc *priv)
{
	static const unsigned int sequence[] = { 0x0, 0x1, 0x3, 0x7, 0x5, 0x1, 0x0 };
	unsigned int val;
	struct device *dev = &priv->rtc_dev->dev;
	int i, ret;

	/*
	 * This gates iso_en by writing a special sequence of bytes to iso_ctrl
	 * and ensuring that it has been correctly applied by reading iso_ctrl_ack
	 */
	for (i = 0; i < ARRAY_SIZE(sequence); i++) {
		writeb(sequence[i] & ISO_CTRL_MASK, priv->base +  REG_ISO_CTRL);

		ret = read_poll_timeout(read_iso_ctrl_ack, val, val == (i % 2), 100,
					20 * 100, true, priv->base);
		if (ret) {
			dev_dbg(dev, "Timeout waiting for ack byte %i (%x) of sequence\n", i,
				sequence[i]);
			return ret;
		}
	}

	/*
	 * At this point iso_en should be raised for 1ms
	 */
	ret = read_poll_timeout(read_iso_en, val, val, 100, 22 * 100, true, priv->base);
	if (ret)
		dev_dbg(dev, "Timeout waiting for iso_en\n");
	mdelay(2);
	return 0;
}

static void ssd202d_rtc_read_reg(struct ssd202d_rtc *priv, unsigned int reg,
				 unsigned int field, unsigned int *base)
{
	unsigned int l, h;
	u16 val;

	/* Ask for the content of an RTC value into RDDATA by gating iso_en,
	 * then iso_en is gated and the content of RDDATA can be read
	 */
	val = readw(priv->base + reg);
	writew(val | field, priv->base + reg);
	ssd202d_rtc_isoctrl(priv);
	writew(val & ~field, priv->base + reg);

	l = readw(priv->base + REG_RDDATA_L);
	h = readw(priv->base + REG_RDDATA_H);

	*base = (h << 16) | l;
}

static void ssd202d_rtc_write_reg(struct ssd202d_rtc *priv, unsigned int reg,
				  unsigned int field, u32 base)
{
	u16 val;

	/* Set the content of an RTC value from WRDATA by gating iso_en */
	val = readw(priv->base + reg);
	writew(val | field, priv->base + reg);
	writew(base, priv->base + REG_WRDATA_L);
	writew(base >> 16, priv->base + REG_WRDATA_H);
	ssd202d_rtc_isoctrl(priv);
	writew(val & ~field, priv->base + reg);
}

static int ssd202d_rtc_read_counter(struct ssd202d_rtc *priv, unsigned int *counter)
{
	unsigned int l, h;
	u16 val;

	val = readw(priv->base + REG_CTRL1);
	writew(val | CNT_RD_BIT, priv->base + REG_CTRL1);
	ssd202d_rtc_isoctrl(priv);

Annotation

Implementation Notes