drivers/soc/qcom/pmic_pdcharger_ulog.c

Source file repositories/reference/linux-study-clean/drivers/soc/qcom/pmic_pdcharger_ulog.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/qcom/pmic_pdcharger_ulog.c
Extension
.c
Size
4116 bytes
Lines
171
Domain
Driver Families
Bucket
drivers/soc
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 pmic_pdcharger_ulog_hdr {
	__le32 owner;
	__le32 type;
	__le32 opcode;
};

struct pmic_pdcharger_ulog {
	struct rpmsg_device *rpdev;
	struct delayed_work ulog_work;
};

struct get_ulog_req_msg {
	struct pmic_pdcharger_ulog_hdr	hdr;
	u32				log_size;
};

struct get_ulog_resp_msg {
	struct pmic_pdcharger_ulog_hdr	hdr;
	u8				buf[MAX_ULOG_SIZE];
};

static int pmic_pdcharger_ulog_write_async(struct pmic_pdcharger_ulog *pg, void *data, size_t len)
{
	return rpmsg_send(pg->rpdev->ept, data, len);
}

static int pmic_pdcharger_ulog_request(struct pmic_pdcharger_ulog *pg)
{
	struct get_ulog_req_msg req_msg = {
		.hdr = {
			.owner = cpu_to_le32(MSG_OWNER_CHG_ULOG),
			.type = cpu_to_le32(MSG_TYPE_REQ_RESP),
			.opcode = cpu_to_le32(GET_CHG_ULOG_REQ)
		},
		.log_size = MAX_ULOG_SIZE
	};

	return pmic_pdcharger_ulog_write_async(pg, &req_msg, sizeof(req_msg));
}

static void pmic_pdcharger_ulog_work(struct work_struct *work)
{
	struct pmic_pdcharger_ulog *pg = container_of(work, struct pmic_pdcharger_ulog,
						      ulog_work.work);
	int rc;

	rc = pmic_pdcharger_ulog_request(pg);
	if (rc) {
		dev_err(&pg->rpdev->dev, "Error requesting ulog, rc=%d\n", rc);
		return;
	}
}

static void pmic_pdcharger_ulog_handle_message(struct pmic_pdcharger_ulog *pg,
					       struct get_ulog_resp_msg *resp_msg,
					       size_t len)
{
	char *token, *buf = resp_msg->buf;

	if (len != sizeof(*resp_msg)) {
		dev_err(&pg->rpdev->dev, "Expected data length: %zu, received: %zu\n",
			sizeof(*resp_msg), len);
		return;
	}

	buf[MAX_ULOG_SIZE - 1] = '\0';

	do {
		token = strsep((char **)&buf, "\n");
		if (token && strlen(token))
			trace_pmic_pdcharger_ulog_msg(token);
	} while (token);
}

static int pmic_pdcharger_ulog_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
					      int len, void *priv, u32 addr)
{
	struct pmic_pdcharger_ulog *pg = dev_get_drvdata(&rpdev->dev);
	struct pmic_pdcharger_ulog_hdr *hdr = data;
	u32 opcode;

	opcode = le32_to_cpu(hdr->opcode);

	switch (opcode) {
	case GET_CHG_ULOG_REQ:
		schedule_delayed_work(&pg->ulog_work, msecs_to_jiffies(LOG_DEFAULT_TIME_MS));
		pmic_pdcharger_ulog_handle_message(pg, data, len);
		break;
	default:
		dev_err(&pg->rpdev->dev, "Unknown opcode %u\n", opcode);

Annotation

Implementation Notes