drivers/w1/masters/omap_hdq.c

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

File Facts

System
Linux kernel
Corpus path
drivers/w1/masters/omap_hdq.c
Extension
.c
Size
17197 bytes
Lines
682
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 hdq_data {
	struct device		*dev;
	void __iomem		*hdq_base;
	/* lock read/write/break operations */
	struct  mutex		hdq_mutex;
	/* interrupt status and a lock for it */
	u8			hdq_irqstatus;
	spinlock_t		hdq_spinlock;
	/* mode: 0-HDQ 1-W1 */
	int                     mode;

};

/* HDQ register I/O routines */
static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)
{
	return __raw_readl(hdq_data->hdq_base + offset);
}

static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)
{
	__raw_writel(val, hdq_data->hdq_base + offset);
}

static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
			u8 val, u8 mask)
{
	u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)
			| (val & mask);
	__raw_writel(new_val, hdq_data->hdq_base + offset);

	return new_val;
}

/*
 * Wait for one or more bits in flag change.
 * HDQ_FLAG_SET: wait until any bit in the flag is set.
 * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared.
 * return 0 on success and -ETIMEDOUT in the case of timeout.
 */
static int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset,
		u8 flag, u8 flag_set, u8 *status)
{
	int ret = 0;
	unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;

	if (flag_set == OMAP_HDQ_FLAG_CLEAR) {
		/* wait for the flag clear */
		while (((*status = hdq_reg_in(hdq_data, offset)) & flag)
			&& time_before(jiffies, timeout)) {
			schedule_timeout_uninterruptible(1);
		}
		if (*status & flag)
			ret = -ETIMEDOUT;
	} else if (flag_set == OMAP_HDQ_FLAG_SET) {
		/* wait for the flag set */
		while (!((*status = hdq_reg_in(hdq_data, offset)) & flag)
			&& time_before(jiffies, timeout)) {
			schedule_timeout_uninterruptible(1);
		}
		if (!(*status & flag))
			ret = -ETIMEDOUT;
	} else
		return -EINVAL;

	return ret;
}

/* Clear saved irqstatus after using an interrupt */
static u8 hdq_reset_irqstatus(struct hdq_data *hdq_data, u8 bits)
{
	unsigned long irqflags;
	u8 status;

	spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
	status = hdq_data->hdq_irqstatus;
	/* this is a read-modify-write */
	hdq_data->hdq_irqstatus &= ~bits;
	spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);

	return status;
}

/* write out a byte and fill *status with HDQ_INT_STATUS */
static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
{
	int ret;
	u8 tmp_status;

	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);

Annotation

Implementation Notes