drivers/w1/masters/amd_axi_w1.c

Source file repositories/reference/linux-study-clean/drivers/w1/masters/amd_axi_w1.c

File Facts

System
Linux kernel
Corpus path
drivers/w1/masters/amd_axi_w1.c
Extension
.c
Size
12169 bytes
Lines
397
Domain
Driver Families
Bucket
drivers/w1
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 amd_axi_w1_local {
	struct device *dev;
	void __iomem *base_addr;
	int irq;
	atomic_t flag;			/* Set on IRQ, cleared once serviced */
	wait_queue_head_t wait_queue;
	struct w1_bus_master bus_host;
};

/**
 * amd_axi_w1_wait_irq_interruptible_timeout() - Wait for IRQ with timeout.
 *
 * @amd_axi_w1_local:	Pointer to device structure
 * @IRQ:		IRQ channel to wait on
 *
 * Return:		%0 - OK, %-EINTR - Interrupted, %-EBUSY - Timed out
 */
static int amd_axi_w1_wait_irq_interruptible_timeout(struct amd_axi_w1_local *amd_axi_w1_local,
						     u32 IRQ)
{
	int ret;

	/* Enable the IRQ requested and wait for flag to indicate it's been triggered */
	iowrite32(IRQ, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG);
	ret = wait_event_interruptible_timeout(amd_axi_w1_local->wait_queue,
					       atomic_read(&amd_axi_w1_local->flag) != 0,
					       AXIW1_TIMEOUT);
	if (ret < 0) {
		dev_err(amd_axi_w1_local->dev, "Wait IRQ Interrupted\n");
		return -EINTR;
	}

	if (!ret) {
		dev_err(amd_axi_w1_local->dev, "Wait IRQ Timeout\n");
		return -EBUSY;
	}

	atomic_set(&amd_axi_w1_local->flag, 0);
	return 0;
}

/**
 * amd_axi_w1_touch_bit() - Performs the touch-bit function - write a 0 or 1 and reads the level.
 *
 * @data:	Pointer to device structure
 * @bit:	The level to write
 *
 * Return:	The level read
 */
static u8 amd_axi_w1_touch_bit(void *data, u8 bit)
{
	struct amd_axi_w1_local *amd_axi_w1_local = data;
	u8 val = 0;
	int rc;

	/* Wait for READY signal to be 1 to ensure 1-wire IP is ready */
	while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) {
		rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local,
							       AXIW1_READY_IRQ_EN);
		if (rc < 0)
			return 1; /* Callee doesn't test for error. Return inactive bus state */
	}

	if (bit)
		/* Read. Write read Bit command in register 0 */
		iowrite32(AXIW1_READBIT, amd_axi_w1_local->base_addr + AXIW1_INST_REG);
	else
		/* Write. Write tx Bit command in instruction register with bit to transmit */
		iowrite32(AXIW1_WRITEBIT + (bit & 0x01),
			  amd_axi_w1_local->base_addr + AXIW1_INST_REG);

	/* Write Go signal and clear control reset signal in control register */
	iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);

	/* Wait for done signal to be 1 */
	while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) {
		rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN);
		if (rc < 0)
			return 1; /* Callee doesn't test for error. Return inactive bus state */
	}

	/* If read, Retrieve data from register */
	if (bit)
		val = (u8)(ioread32(amd_axi_w1_local->base_addr + AXIW1_DATA_REG) & AXIW1_READDATA);

	/* Clear Go signal in register 1 */
	iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);

	return val;
}

Annotation

Implementation Notes