[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <e847c9cf-e3ec-4f0c-a7c9-0a827333a4be@linaro.org>
Date: Thu, 30 Nov 2023 10:51:55 +0100
From: Neil Armstrong <neil.armstrong@...aro.org>
To: Andy Gross <agross@...nel.org>,
Bjorn Andersson <andersson@...nel.org>,
Konrad Dybcio <konrad.dybcio@...aro.org>
Cc: linux-kernel@...r.kernel.org, linux-arm-msm@...r.kernel.org
Subject: Re: [PATCH] soc: qcom: add ADSP PDCharger ULOG driver
Hi Bjorn,
On 08/09/2023 12:53, Neil Armstrong wrote:
> The Qualcomm PMIC PDCharger ULOG driver provides access to logs of
> the ADSP firmware PDCharger module in charge of Battery and Power
> Delivery on modern systems.
>
> Implement trace events as a simple rpmsg driver with an 1s interval
> to retrieve the messages.
>
> The interface allows filtering the messages by subsystem and priority
> level, this could be implemented later on.
Any thoughts on this? It's pretty handy to debug PDCharger firmware events,
even more with enhanced usage of UCSI.
Neil
>
> Signed-off-by: Neil Armstrong <neil.armstrong@...aro.org>
> ---
> drivers/soc/qcom/Kconfig | 12 +++
> drivers/soc/qcom/Makefile | 1 +
> drivers/soc/qcom/pmic_pdcharger_ulog.c | 166 +++++++++++++++++++++++++++++++++
> drivers/soc/qcom/pmic_pdcharger_ulog.h | 36 +++++++
> 4 files changed, 215 insertions(+)
>
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index e597799e8121..5f63df3d5d6f 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -93,6 +93,18 @@ config QCOM_PDR_HELPERS
> select QCOM_QMI_HELPERS
> depends on NET
>
> +config QCOM_PMIC_PDCHARGER_ULOG
> + tristate "Qualcomm PMIC PDCharger ULOG driver"
> + depends on RPMSG
> + depends on EVENT_TRACING
> + help
> + The Qualcomm PMIC PDCharger ULOG driver provides access to logs of
> + the ADSP firmware PDCharger module in charge of Battery and Power
> + Delivery on modern systems.
> +
> + Say yes here to support PDCharger ULOG event tracing on modern
> + Qualcomm platforms.
> +
> config QCOM_PMIC_GLINK
> tristate "Qualcomm PMIC GLINK driver"
> depends on RPMSG
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index 99114c71092b..44f6efe9a48c 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
> obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
> obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
> obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
> +obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
> obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
> qmi_helpers-y += qmi_encdec.o qmi_interface.o
> obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o
> diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.c b/drivers/soc/qcom/pmic_pdcharger_ulog.c
> new file mode 100644
> index 000000000000..f1aaacf05005
> --- /dev/null
> +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.c
> @@ -0,0 +1,166 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2019-2022, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023, Linaro Ltd
> + */
> +#include <linux/of_device.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/rpmsg.h>
> +#include <linux/slab.h>
> +#include <linux/soc/qcom/pdr.h>
> +#include <linux/debugfs.h>
> +
> +#define CREATE_TRACE_POINTS
> +#include "pmic_pdcharger_ulog.h"
> +
> +#define MSG_OWNER_CHG_ULOG 32778
> +#define MSG_TYPE_REQ_RESP 1
> +
> +#define GET_CHG_ULOG_REQ 0x18
> +#define SET_CHG_ULOG_PROP_REQ 0x19
> +
> +#define LOG_DEFAULT_TIME_MS 1000
> +
> +#define MAX_ULOG_SIZE 8192
> +
> +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 = MSG_OWNER_CHG_ULOG,
> + .type = MSG_TYPE_REQ_RESP,
> + .opcode = 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);
> + break;
> + }
> +
> + return 0;
> +}
> +
> +static int pmic_pdcharger_ulog_rpmsg_probe(struct rpmsg_device *rpdev)
> +{
> + struct pmic_pdcharger_ulog *pg;
> + struct device *dev = &rpdev->dev;
> +
> + pg = devm_kzalloc(dev, sizeof(*pg), GFP_KERNEL);
> + if (!pg)
> + return -ENOMEM;
> +
> + pg->rpdev = rpdev;
> + INIT_DELAYED_WORK(&pg->ulog_work, pmic_pdcharger_ulog_work);
> +
> + dev_set_drvdata(dev, pg);
> +
> + pmic_pdcharger_ulog_request(pg);
> +
> + return 0;
> +}
> +
> +static void pmic_pdcharger_ulog_rpmsg_remove(struct rpmsg_device *rpdev)
> +{
> + struct pmic_pdcharger_ulog *pg = dev_get_drvdata(&rpdev->dev);
> +
> + cancel_delayed_work_sync(&pg->ulog_work);
> +}
> +
> +static const struct rpmsg_device_id pmic_pdcharger_ulog_rpmsg_id_match[] = {
> + { "PMIC_LOGS_ADSP_APPS" },
> + {}
> +};
> +
> +static struct rpmsg_driver pmic_pdcharger_ulog_rpmsg_driver = {
> + .probe = pmic_pdcharger_ulog_rpmsg_probe,
> + .remove = pmic_pdcharger_ulog_rpmsg_remove,
> + .callback = pmic_pdcharger_ulog_rpmsg_callback,
> + .id_table = pmic_pdcharger_ulog_rpmsg_id_match,
> + .drv = {
> + .name = "qcom_pmic_pdcharger_ulog_rpmsg",
> + },
> +};
> +
> +module_rpmsg_driver(pmic_pdcharger_ulog_rpmsg_driver);
> +MODULE_DESCRIPTION("Qualcomm PMIC ChargerPD ULOG driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.h b/drivers/soc/qcom/pmic_pdcharger_ulog.h
> new file mode 100644
> index 000000000000..9d5d9af4fbe4
> --- /dev/null
> +++ b/drivers/soc/qcom/pmic_pdcharger_ulog.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2023, Linaro Ltd
> + */
> +
> +#if !defined(_TRACE_PMIC_PDCHARGER_ULOG_H) || defined(TRACE_HEADER_MULTI_READ)
> +#define _TRACE_PMIC_PDCHARGER_ULOG_H
> +
> +#include <linux/tracepoint.h>
> +
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM pmic_pdcharger_ulog
> +
> +TRACE_EVENT(pmic_pdcharger_ulog_msg,
> + TP_PROTO(char *msg),
> + TP_ARGS(msg),
> + TP_STRUCT__entry(
> + __string(msg, msg)
> + ),
> + TP_fast_assign(
> + __assign_str(msg, msg);
> + ),
> + TP_printk("%s", __get_str(msg))
> +);
> +
> +#endif /* _TRACE_PMIC_PDCHARGER_ULOG_H */
> +
> +/* This part must be outside protection */
> +
> +#undef TRACE_INCLUDE_PATH
> +#define TRACE_INCLUDE_PATH .
> +
> +#undef TRACE_INCLUDE_FILE
> +#define TRACE_INCLUDE_FILE pmic_pdcharger_ulog
> +
> +#include <trace/define_trace.h>
>
> ---
> base-commit: 2dde18cd1d8fac735875f2e4987f11817cc0bc2c
> change-id: 20230908-topic-sm8550-upstream-pdcharge-ulog-21ece9292474
>
> Best regards,
Powered by blists - more mailing lists