// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
staticvoid qcom_print_stats(struct seq_file *s, conststruct sleep_stats *stat)
{
u64 accumulated = stat->accumulated; /* * If a subsystem is in sleep when reading the sleep stats adjust * the accumulated sleep duration to show actual sleep time.
*/ if (stat->last_entered_at > stat->last_exited_at)
accumulated += arch_timer_read_counter() - stat->last_entered_at;
/* Items are allocated lazily, so lookup pointer each time */
stat = qcom_smem_get(subsystem->pid, subsystem->smem_item, NULL); if (IS_ERR(stat)) return 0;
/* * DDR statistic have two different types of details encoded. * (1) DDR LPM Stats * (2) DDR Frequency Stats * * The name field have details like which type of DDR stat (bits 8:15) * along with other details as explained below * * In case of DDR LPM stat, name field will be encoded as, * Bits - Meaning * 0:7 - DDR LPM name, can be of 0xd4, 0xd3, 0x11 and 0xd0. * 8:15 - 0x0 (indicates its a LPM stat) * 16:31 - Unused * * In case of DDR FREQ stats, name field will be encoded as, * Bits - Meaning * 0:4 - DDR Clock plan index (CP IDX) * 5:7 - Unused * 8:15 - 0x1 (indicates its Freq stat) * 16:31 - Frequency value in Mhz
*/ switch (DDR_STATS_TYPE(data->name)) { case 0:
seq_printf(s, "DDR LPM Stat Name:0x%lx\tcount:%u\tDuration (ticks):%llu\n",
DDR_STATS_LPM_NAME(data->name), data->count, data->duration); break; case 1: if (!data->count || !DDR_STATS_FREQ(data->name)) return;
if (qcom_stats_qmp) { /* * Recent SoCs (SM8450 onwards) do not have duration field * populated from boot up onwards for both DDR LPM Stats * and DDR Frequency Stats. * * Send QMP message to Always on processor which will * populate duration field into MSG RAM area. * * Sent every time to read latest data.
*/
ret = qmp_send(qcom_stats_qmp, "{class: ddr, action: freqsync}"); if (ret) return ret;
}
/* * On RPM targets, stats offset location is dynamic and changes from target * to target and sometimes from build to build for same target. * * In such cases the dynamic address is present at 0x14 offset from base * address in devicetree. The last 16bits indicates the stats_offset.
*/ if (config->dynamic_offset) {
stats_offset = readl(reg + RPM_DYNAMIC_ADDR);
stats_offset &= RPM_DYNAMIC_ADDR_MASK;
}
for (i = 0; i < config->num_records; i++) {
d[i].base = reg + offset + stats_offset;
/* * Read the low power mode name and create debugfs file for it. * The names read could be of below, * (may change depending on low power mode supported). * For rpmh-sleep-stats: "aosd", "cxsd" and "ddr". * For rpm-sleep-stats: "vmin" and "vlow".
*/
type = readl(d[i].base); for (j = 0; j < sizeof(u32); j++) {
stat_type[j] = type & 0xff;
type = type >> 8;
}
strim(stat_type);
debugfs_create_file(stat_type, 0400, root, &d[i],
&qcom_soc_sleep_stats_fops);
staticvoid qcom_create_subsystem_stat_files(struct dentry *root, conststruct stats_config *config)
{ int i;
if (!config->subsystem_stats_in_smem) return;
for (i = 0; i < ARRAY_SIZE(subsystems); i++)
debugfs_create_file(subsystems[i].name, 0400, root, (void *)&subsystems[i],
&qcom_subsystem_sleep_stats_fops);
}
config = device_get_match_data(&pdev->dev); if (!config) return -ENODEV;
reg = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(reg)) return -ENOMEM;
d = devm_kcalloc(&pdev->dev, config->num_records, sizeof(*d), GFP_KERNEL); if (!d) return -ENOMEM;
for (i = 0; i < config->num_records; i++)
d[i].appended_stats_avail = config->appended_stats_avail; /* * QMP is used for DDR stats syncing to MSG RAM for recent SoCs (SM8450 onwards). * The prior SoCs do not need QMP handle as the required stats are already present * in MSG RAM, provided the DDR_STATS_MAGIC_KEY matches.
*/
qcom_stats_qmp = qmp_get(&pdev->dev); if (IS_ERR(qcom_stats_qmp)) { /* We ignore error if QMP is not defined/needed */ if (!of_property_present(pdev->dev.of_node, "qcom,qmp"))
qcom_stats_qmp = NULL; elseif (PTR_ERR(qcom_stats_qmp) == -EPROBE_DEFER) return -EPROBE_DEFER; else return PTR_ERR(qcom_stats_qmp);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.