Loading drivers/soc/qcom/Kconfig +8 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,14 @@ config MSM_SERVICE_NOTIFIER like audio, the identifier for which is provided by the service locator. config MSM_BOOT_STATS tristate "Use MSM boot stats reporting" help Use this to report msm boot stats such as bootloader throughput, display init, total boot time. This figures are reported in mpm sleep clock cycles and have a resolution of 31 bits as 1 bit is used as an overflow check. config QCOM_QMI_HELPERS tristate depends on ARCH_QCOM || COMPILE_TEST Loading drivers/soc/qcom/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o obj-$(CONFIG_QCOM_SOC_SLEEP_STATS) += soc_sleep_stats.o obj-$(CONFIG_MSM_BOOT_STATS) += boot_stats.o obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o obj-$(CONFIG_QCOM_SMEM) += smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o Loading drivers/soc/qcom/boot_stats.c 0 → 100644 +113 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> #include <linux/err.h> #include <linux/io.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/cpu.h> #include <linux/sched.h> #include <linux/of.h> #include <linux/of_address.h> struct boot_stats { uint32_t bootloader_start; uint32_t bootloader_end; uint32_t bootloader_display; uint32_t bootloader_load_kernel; }; static void __iomem *mpm_counter_base; static uint32_t mpm_counter_freq; static struct boot_stats __iomem *boot_stats; static int mpm_parse_dt(void) { struct device_node *np_imem, *np_mpm2; np_imem = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-boot_stats"); if (!np_imem) { pr_err("can't find qcom,msm-imem node\n"); return -ENODEV; } boot_stats = of_iomap(np_imem, 0); if (!boot_stats) { pr_err("boot_stats: Can't map imem\n"); goto err1; } np_mpm2 = of_find_compatible_node(NULL, NULL, "qcom,mpm2-sleep-counter"); if (!np_mpm2) { pr_err("mpm_counter: can't find DT node\n"); goto err1; } if (of_property_read_u32(np_mpm2, "clock-frequency", &mpm_counter_freq)) goto err2; if (of_get_address(np_mpm2, 0, NULL, NULL)) { mpm_counter_base = of_iomap(np_mpm2, 0); if (!mpm_counter_base) { pr_err("mpm_counter: cant map counter base\n"); goto err2; } } else goto err2; return 0; err2: of_node_put(np_mpm2); err1: of_node_put(np_imem); return -ENODEV; } static void print_boot_stats(void) { pr_info("KPI: Bootloader start count = %u\n", readl_relaxed(&boot_stats->bootloader_start)); pr_info("KPI: Bootloader end count = %u\n", readl_relaxed(&boot_stats->bootloader_end)); pr_info("KPI: Bootloader display count = %u\n", readl_relaxed(&boot_stats->bootloader_display)); pr_info("KPI: Bootloader load kernel count = %u\n", readl_relaxed(&boot_stats->bootloader_load_kernel)); pr_info("KPI: Kernel MPM timestamp = %u\n", readl_relaxed(mpm_counter_base)); pr_info("KPI: Kernel MPM Clock frequency = %u\n", mpm_counter_freq); } static int __init boot_stats_init(void) { int ret; ret = mpm_parse_dt(); if (ret < 0) return -ENODEV; print_boot_stats(); iounmap(boot_stats); iounmap(mpm_counter_base); return 0; } module_init(boot_stats_init); static void __exit boot_stats_exit(void) { } module_exit(boot_stats_exit) MODULE_DESCRIPTION("MSM boot stats info driver"); MODULE_LICENSE("GPL v2"); Loading
drivers/soc/qcom/Kconfig +8 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,14 @@ config MSM_SERVICE_NOTIFIER like audio, the identifier for which is provided by the service locator. config MSM_BOOT_STATS tristate "Use MSM boot stats reporting" help Use this to report msm boot stats such as bootloader throughput, display init, total boot time. This figures are reported in mpm sleep clock cycles and have a resolution of 31 bits as 1 bit is used as an overflow check. config QCOM_QMI_HELPERS tristate depends on ARCH_QCOM || COMPILE_TEST Loading
drivers/soc/qcom/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o obj-$(CONFIG_QCOM_SOC_SLEEP_STATS) += soc_sleep_stats.o obj-$(CONFIG_MSM_BOOT_STATS) += boot_stats.o obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o obj-$(CONFIG_QCOM_SMEM) += smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o Loading
drivers/soc/qcom/boot_stats.c 0 → 100644 +113 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> #include <linux/err.h> #include <linux/io.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/cpu.h> #include <linux/sched.h> #include <linux/of.h> #include <linux/of_address.h> struct boot_stats { uint32_t bootloader_start; uint32_t bootloader_end; uint32_t bootloader_display; uint32_t bootloader_load_kernel; }; static void __iomem *mpm_counter_base; static uint32_t mpm_counter_freq; static struct boot_stats __iomem *boot_stats; static int mpm_parse_dt(void) { struct device_node *np_imem, *np_mpm2; np_imem = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-boot_stats"); if (!np_imem) { pr_err("can't find qcom,msm-imem node\n"); return -ENODEV; } boot_stats = of_iomap(np_imem, 0); if (!boot_stats) { pr_err("boot_stats: Can't map imem\n"); goto err1; } np_mpm2 = of_find_compatible_node(NULL, NULL, "qcom,mpm2-sleep-counter"); if (!np_mpm2) { pr_err("mpm_counter: can't find DT node\n"); goto err1; } if (of_property_read_u32(np_mpm2, "clock-frequency", &mpm_counter_freq)) goto err2; if (of_get_address(np_mpm2, 0, NULL, NULL)) { mpm_counter_base = of_iomap(np_mpm2, 0); if (!mpm_counter_base) { pr_err("mpm_counter: cant map counter base\n"); goto err2; } } else goto err2; return 0; err2: of_node_put(np_mpm2); err1: of_node_put(np_imem); return -ENODEV; } static void print_boot_stats(void) { pr_info("KPI: Bootloader start count = %u\n", readl_relaxed(&boot_stats->bootloader_start)); pr_info("KPI: Bootloader end count = %u\n", readl_relaxed(&boot_stats->bootloader_end)); pr_info("KPI: Bootloader display count = %u\n", readl_relaxed(&boot_stats->bootloader_display)); pr_info("KPI: Bootloader load kernel count = %u\n", readl_relaxed(&boot_stats->bootloader_load_kernel)); pr_info("KPI: Kernel MPM timestamp = %u\n", readl_relaxed(mpm_counter_base)); pr_info("KPI: Kernel MPM Clock frequency = %u\n", mpm_counter_freq); } static int __init boot_stats_init(void) { int ret; ret = mpm_parse_dt(); if (ret < 0) return -ENODEV; print_boot_stats(); iounmap(boot_stats); iounmap(mpm_counter_base); return 0; } module_init(boot_stats_init); static void __exit boot_stats_exit(void) { } module_exit(boot_stats_exit) MODULE_DESCRIPTION("MSM boot stats info driver"); MODULE_LICENSE("GPL v2");