drivers/rtc/rtc-meson.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-meson.c
Extension
.c
Size
10546 bytes
Lines
405
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 meson_rtc {
	struct device		*dev;		/* device we bound from */
	struct reset_control	*reset;		/* reset source */
	struct regulator	*vdd;		/* voltage input */
	struct regmap		*peripheral;	/* peripheral registers */
	struct regmap		*serial;	/* serial registers */
};

static const struct regmap_config meson_rtc_peripheral_regmap_config = {
	.name		= "peripheral-registers",
	.reg_bits	= 8,
	.val_bits	= 32,
	.reg_stride	= 4,
	.max_register	= RTC_REG4,
};

/* RTC front-end serialiser controls */

static void meson_rtc_sclk_pulse(struct meson_rtc *rtc)
{
	udelay(5);
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SCLK, 0);
	udelay(5);
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SCLK,
			   RTC_ADDR0_LINE_SCLK);
}

static void meson_rtc_send_bit(struct meson_rtc *rtc, unsigned int bit)
{
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SDI,
			   bit ? RTC_ADDR0_LINE_SDI : 0);
	meson_rtc_sclk_pulse(rtc);
}

static void meson_rtc_send_bits(struct meson_rtc *rtc, u32 data,
				unsigned int nr)
{
	u32 bit = 1 << (nr - 1);

	while (bit) {
		meson_rtc_send_bit(rtc, data & bit);
		bit >>= 1;
	}
}

static void meson_rtc_set_dir(struct meson_rtc *rtc, u32 mode)
{
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SEN, 0);
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SDI, 0);
	meson_rtc_send_bit(rtc, mode);
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SDI, 0);
}

static u32 meson_rtc_get_data(struct meson_rtc *rtc)
{
	u32 tmp, val = 0;
	int bit;

	for (bit = 0; bit < RTC_DATA_BITS; bit++) {
		meson_rtc_sclk_pulse(rtc);
		val <<= 1;

		regmap_read(rtc->peripheral, RTC_ADDR1, &tmp);
		val |= tmp & RTC_ADDR1_SDO;
	}

	return val;
}

static int meson_rtc_get_bus(struct meson_rtc *rtc)
{
	int ret, retries;
	u32 val;

	/* prepare bus for transfers, set all lines low */
	val = RTC_ADDR0_LINE_SDI | RTC_ADDR0_LINE_SEN | RTC_ADDR0_LINE_SCLK;
	regmap_update_bits(rtc->peripheral, RTC_ADDR0, val, 0);

	for (retries = 0; retries < 3; retries++) {
		/* wait for the bus to be ready */
		if (!regmap_read_poll_timeout(rtc->peripheral, RTC_ADDR1, val,
					      val & RTC_ADDR1_S_READY, 10,
					      10000))
			return 0;

		dev_warn(rtc->dev, "failed to get bus, resetting RTC\n");

		ret = reset_control_reset(rtc->reset);
		if (ret)
			return ret;

Annotation

Implementation Notes