123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2013-2019, 2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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_load_boot_start;
- uint32_t bootloader_load_boot_end;
- uint32_t bootloader_load_vendor_boot_start;
- uint32_t bootloader_load_vendor_boot_end;
- uint32_t bootloader_load_init_boot_start;
- uint32_t bootloader_load_init_boot_end;
- } __packed;
- 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 load kernel count = %u\n",
- readl_relaxed(&boot_stats->bootloader_load_boot_end) -
- readl_relaxed(&boot_stats->bootloader_load_boot_start));
- 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");
|