drivers/hwmon/xgene-hwmon.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/xgene-hwmon.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/xgene-hwmon.c
Extension
.c
Size
18614 bytes
Lines
755
Domain
Driver Families
Bucket
drivers/hwmon
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 slimpro_resp_msg {
	u32 msg;
	u32 param1;
	u32 param2;
} __packed;

struct xgene_hwmon_dev {
	struct device		*dev;
	struct mbox_chan	*mbox_chan;
	struct pcc_mbox_chan	*pcc_chan;
	struct mbox_client	mbox_client;
	int			mbox_idx;

	spinlock_t		kfifo_lock;
	struct mutex		rd_mutex;
	struct completion	rd_complete;
	int			resp_pending;
	struct slimpro_resp_msg sync_msg;

	struct work_struct	workq;
	struct kfifo_rec_ptr_1	async_msg_fifo;

	struct device		*hwmon_dev;
	bool			temp_critical_alarm;

	unsigned int		usecs_lat;
};

/*
 * This function tests and clears a bitmask then returns its old value
 */
static u16 xgene_word_tst_and_clr(u16 *addr, u16 mask)
{
	u16 ret, val;

	val = le16_to_cpu(READ_ONCE(*addr));
	ret = val & mask;
	val &= ~mask;
	WRITE_ONCE(*addr, cpu_to_le16(val));

	return ret;
}

static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
{
	struct acpi_pcct_shared_memory __iomem *generic_comm_base =
							ctx->pcc_chan->shmem;
	u32 *ptr = (void *)(generic_comm_base + 1);
	int rc, i;
	u16 val;

	mutex_lock(&ctx->rd_mutex);
	init_completion(&ctx->rd_complete);
	ctx->resp_pending = true;

	/* Write signature for subspace */
	WRITE_ONCE(generic_comm_base->signature,
		   cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx));

	/* Write to the shared command region */
	WRITE_ONCE(generic_comm_base->command,
		   cpu_to_le16(MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR));

	/* Flip CMD COMPLETE bit */
	val = le16_to_cpu(READ_ONCE(generic_comm_base->status));
	val &= ~PCC_STATUS_CMD_COMPLETE;
	WRITE_ONCE(generic_comm_base->status, cpu_to_le16(val));

	/* Copy the message to the PCC comm space */
	for (i = 0; i < sizeof(struct slimpro_resp_msg) / 4; i++)
		WRITE_ONCE(ptr[i], cpu_to_le32(msg[i]));

	/* Ring the doorbell */
	rc = mbox_send_message(ctx->mbox_chan, msg);
	if (rc < 0) {
		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
		goto err;
	}
	if (!wait_for_completion_timeout(&ctx->rd_complete,
					 usecs_to_jiffies(ctx->usecs_lat))) {
		dev_err(ctx->dev, "Mailbox operation timed out\n");
		rc = -ETIMEDOUT;
		goto err;
	}

	/* Check for error message */
	if (MSG_TYPE(ctx->sync_msg.msg) == MSG_TYPE_ERR) {
		rc = -EINVAL;
		goto err;
	}

Annotation

Implementation Notes