drivers/rtc/rtc-ds2404.c

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

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-ds2404.c
Extension
.c
Size
5127 bytes
Lines
226
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 ds2404 {
	struct device *dev;
	struct gpio_desc *rst_gpiod;
	struct gpio_desc *clk_gpiod;
	struct gpio_desc *dq_gpiod;
};

static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;

	/* This will de-assert RESET, declare this GPIO as GPIOD_ACTIVE_LOW */
	chip->rst_gpiod = devm_gpiod_get(dev, "rst", GPIOD_OUT_LOW);
	if (IS_ERR(chip->rst_gpiod))
		return PTR_ERR(chip->rst_gpiod);

	chip->clk_gpiod = devm_gpiod_get(dev, "clk", GPIOD_OUT_HIGH);
	if (IS_ERR(chip->clk_gpiod))
		return PTR_ERR(chip->clk_gpiod);

	chip->dq_gpiod = devm_gpiod_get(dev, "dq", GPIOD_ASIS);
	if (IS_ERR(chip->dq_gpiod))
		return PTR_ERR(chip->dq_gpiod);

	return 0;
}

static void ds2404_reset(struct ds2404 *chip)
{
	gpiod_set_value(chip->rst_gpiod, 1);
	udelay(1000);
	gpiod_set_value(chip->rst_gpiod, 0);
	gpiod_set_value(chip->clk_gpiod, 0);
	gpiod_direction_output(chip->dq_gpiod, 0);
	udelay(10);
}

static void ds2404_write_byte(struct ds2404 *chip, u8 byte)
{
	int i;

	gpiod_direction_output(chip->dq_gpiod, 1);
	for (i = 0; i < 8; i++) {
		gpiod_set_value(chip->dq_gpiod, byte & (1 << i));
		udelay(10);
		gpiod_set_value(chip->clk_gpiod, 1);
		udelay(10);
		gpiod_set_value(chip->clk_gpiod, 0);
		udelay(10);
	}
}

static u8 ds2404_read_byte(struct ds2404 *chip)
{
	int i;
	u8 ret = 0;

	gpiod_direction_input(chip->dq_gpiod);

	for (i = 0; i < 8; i++) {
		gpiod_set_value(chip->clk_gpiod, 0);
		udelay(10);
		if (gpiod_get_value(chip->dq_gpiod))
			ret |= 1 << i;
		gpiod_set_value(chip->clk_gpiod, 1);
		udelay(10);
	}
	return ret;
}

static void ds2404_read_memory(struct ds2404 *chip, u16 offset,
			       int length, u8 *out)
{
	ds2404_reset(chip);
	ds2404_write_byte(chip, DS2404_READ_MEMORY_CMD);
	ds2404_write_byte(chip, offset & 0xff);
	ds2404_write_byte(chip, (offset >> 8) & 0xff);
	while (length--)
		*out++ = ds2404_read_byte(chip);
}

static void ds2404_write_memory(struct ds2404 *chip, u16 offset,
				int length, u8 *out)
{
	int i;
	u8 ta01, ta02, es;

	ds2404_reset(chip);
	ds2404_write_byte(chip, DS2404_WRITE_SCRATCHPAD_CMD);
	ds2404_write_byte(chip, offset & 0xff);

Annotation

Implementation Notes