Skip to content

Commit e265de1

Browse files
maulik-k-shahandersson
authored andcommitted
soc: qcom: qcom_stats: Add QMP support for syncing ddr stats
Recent SoCs (SM8450 onwards) require QMP command to be sent before reading ddr stats. The duration field of ddr stats will get populated only if QMP command is sent. Add support to send ddr stats freqsync QMP command. Signed-off-by: Maulik Shah <[email protected]> Reviewed-by: Dmitry Baryshkov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 33301e5 commit e265de1

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

drivers/soc/qcom/qcom_stats.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/platform_device.h>
1414
#include <linux/seq_file.h>
1515

16+
#include <linux/soc/qcom/qcom_aoss.h>
1617
#include <linux/soc/qcom/smem.h>
1718
#include <clocksource/arm_arch_timer.h>
1819

@@ -37,6 +38,8 @@
3738
#define DDR_STATS_TYPE(data) FIELD_GET(GENMASK(15, 8), data)
3839
#define DDR_STATS_FREQ(data) FIELD_GET(GENMASK(31, 16), data)
3940

41+
static struct qmp *qcom_stats_qmp;
42+
4043
struct subsystem_data {
4144
const char *name;
4245
u32 smem_item;
@@ -188,12 +191,28 @@ static int qcom_ddr_stats_show(struct seq_file *s, void *d)
188191
struct ddr_stats_entry data[DDR_STATS_MAX_NUM_MODES];
189192
void __iomem *reg = (void __iomem *)s->private;
190193
u32 entry_count;
191-
int i;
194+
int i, ret;
192195

193196
entry_count = readl_relaxed(reg + DDR_STATS_NUM_MODES_ADDR);
194197
if (entry_count > DDR_STATS_MAX_NUM_MODES)
195198
return -EINVAL;
196199

200+
if (qcom_stats_qmp) {
201+
/*
202+
* Recent SoCs (SM8450 onwards) do not have duration field
203+
* populated from boot up onwards for both DDR LPM Stats
204+
* and DDR Frequency Stats.
205+
*
206+
* Send QMP message to Always on processor which will
207+
* populate duration field into MSG RAM area.
208+
*
209+
* Sent every time to read latest data.
210+
*/
211+
ret = qmp_send(qcom_stats_qmp, "{class: ddr, action: freqsync}");
212+
if (ret)
213+
return ret;
214+
}
215+
197216
reg += DDR_STATS_ENTRY_START_ADDR;
198217
memcpy_fromio(data, reg, sizeof(struct ddr_stats_entry) * entry_count);
199218

@@ -304,6 +323,21 @@ static int qcom_stats_probe(struct platform_device *pdev)
304323

305324
for (i = 0; i < config->num_records; i++)
306325
d[i].appended_stats_avail = config->appended_stats_avail;
326+
/*
327+
* QMP is used for DDR stats syncing to MSG RAM for recent SoCs (SM8450 onwards).
328+
* The prior SoCs do not need QMP handle as the required stats are already present
329+
* in MSG RAM, provided the DDR_STATS_MAGIC_KEY matches.
330+
*/
331+
qcom_stats_qmp = qmp_get(&pdev->dev);
332+
if (IS_ERR(qcom_stats_qmp)) {
333+
/* We ignore error if QMP is not defined/needed */
334+
if (!of_property_present(pdev->dev.of_node, "qcom,qmp"))
335+
qcom_stats_qmp = NULL;
336+
else if (PTR_ERR(qcom_stats_qmp) == -EPROBE_DEFER)
337+
return -EPROBE_DEFER;
338+
else
339+
return PTR_ERR(qcom_stats_qmp);
340+
}
307341

308342
root = debugfs_create_dir("qcom_stats", NULL);
309343

0 commit comments

Comments
 (0)