drivers/rtc/rtc-pcf8563.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-pcf8563.c
Extension
.c
Size
15041 bytes
Lines
592
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 pcf8563 {
	struct rtc_device *rtc;
	/*
	 * The meaning of MO_C bit varies by the chip type.
	 * From PCF8563 datasheet: this bit is toggled when the years
	 * register overflows from 99 to 00
	 *   0 indicates the century is 20xx
	 *   1 indicates the century is 19xx
	 * From RTC8564 datasheet: this bit indicates change of
	 * century. When the year digit data overflows from 99 to 00,
	 * this bit is set. By presetting it to 0 while still in the
	 * 20th century, it will be set in year 2000, ...
	 * There seems no reliable way to know how the system use this
	 * bit.  So let's do it heuristically, assuming we are live in
	 * 1970...2069.
	 */
	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */

	struct regmap *regmap;
#ifdef CONFIG_COMMON_CLK
	struct clk_hw		clkout_hw;
#endif
};

static int pcf8563_set_alarm_mode(struct pcf8563 *pcf8563, bool on)
{
	u32 buf;
	int err;

	err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf);
	if (err < 0)
		return err;

	if (on)
		buf |= PCF8563_BIT_AIE;
	else
		buf &= ~PCF8563_BIT_AIE;

	buf &= ~(PCF8563_BIT_AF | PCF8563_BITS_ST2_N);

	return regmap_write(pcf8563->regmap, PCF8563_REG_ST2, buf);
}

static int pcf8563_get_alarm_mode(struct pcf8563 *pcf8563, unsigned char *en,
				  unsigned char *pen)
{
	u32 buf;
	int err;

	err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf);
	if (err < 0)
		return err;

	if (en)
		*en = !!(buf & PCF8563_BIT_AIE);
	if (pen)
		*pen = !!(buf & PCF8563_BIT_AF);

	return 0;
}

static irqreturn_t pcf8563_irq(int irq, void *dev_id)
{
	struct pcf8563 *pcf8563 = dev_id;
	char pending;
	int err;

	err = pcf8563_get_alarm_mode(pcf8563, NULL, &pending);
	if (err)
		return IRQ_NONE;

	if (pending) {
		rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
		pcf8563_set_alarm_mode(pcf8563, 1);
		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}

/*
 * In the routines that deal directly with the pcf8563 hardware, we use
 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
 */
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
	unsigned char buf[9];
	int err;

Annotation

Implementation Notes