From bc2d913a399e735d25fc530b84cc7d4d0f2e2f3e Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Sat, 8 Oct 2022 20:13:59 +0800 Subject: [PATCH] soc: rockchip: opp_select: dump current opp state when panic for cpu/ddr panic log: cpu cpu6: cur_freq: 1008000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV cpu cpu4: cur_freq: 408000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV cpu cpu0: cur_freq: 816000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV rockchip-dmc dmc: cur_freq: 528000000 Hz, volt_vdd: 675000 uV, volt_mem: 700000 uV Change-Id: I29ea94cc9deaba0e1d285390312256567708d6ef Signed-off-by: Liang Chen --- drivers/cpufreq/rockchip-cpufreq.c | 21 +++++++++++ drivers/devfreq/rockchip_dmc.c | 18 ++++++++++ drivers/soc/rockchip/rockchip_opp_select.c | 42 ++++++++++++++++++++++ include/soc/rockchip/rockchip_opp_select.h | 6 ++++ 4 files changed, 87 insertions(+) diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 0067a0cfd708..699f53e15ece 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -899,6 +899,22 @@ static struct notifier_block rockchip_cpufreq_transition_notifier_block = { .notifier_call = rockchip_cpufreq_transition_notifier, }; +static int rockchip_cpufreq_panic_notifier(struct notifier_block *nb, + unsigned long v, void *p) +{ + struct cluster_info *ci; + + list_for_each_entry(ci, &cluster_info_list, list_head) { + rockchip_opp_dump_cur_state(ci->opp_info.dev); + } + + return 0; +} + +static struct notifier_block rockchip_cpufreq_panic_notifier_block = { + .notifier_call = rockchip_cpufreq_panic_notifier, +}; + static int __init rockchip_cpufreq_driver_init(void) { struct cluster_info *cluster, *pos; @@ -948,6 +964,11 @@ static int __init rockchip_cpufreq_driver_init(void) #endif } + ret = atomic_notifier_chain_register(&panic_notifier_list, + &rockchip_cpufreq_panic_notifier_block); + if (ret) + pr_err("failed to register cpufreq panic notifier\n"); + return PTR_ERR_OR_ZERO(platform_device_register_data(NULL, "cpufreq-dt", -1, (void *)&pdata, sizeof(struct cpufreq_dt_platform_data))); diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 1cdb66af9084..4348297316e0 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -118,6 +118,7 @@ struct rockchip_dmcfreq { struct regulator *vdd_center; struct regulator *mem_reg; struct notifier_block status_nb; + struct notifier_block panic_nb; struct list_head video_info_list; struct freq_map_table *cpu_bw_tbl; struct work_struct boost_work; @@ -2576,6 +2577,17 @@ next: return NOTIFY_OK; } +static int rockchip_dmcfreq_panic_notifier(struct notifier_block *nb, + unsigned long v, void *p) +{ + struct rockchip_dmcfreq *dmcfreq = + container_of(nb, struct rockchip_dmcfreq, panic_nb); + + rockchip_opp_dump_cur_state(dmcfreq->dev); + + return 0; +} + static ssize_t rockchip_dmcfreq_status_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -3129,6 +3141,12 @@ static void rockchip_dmcfreq_register_notifier(struct rockchip_dmcfreq *dmcfreq) if (ret) dev_err(dmcfreq->dev, "failed to register system_status nb\n"); + dmcfreq->panic_nb.notifier_call = rockchip_dmcfreq_panic_notifier; + ret = atomic_notifier_chain_register(&panic_notifier_list, + &dmcfreq->panic_nb); + if (ret) + dev_err(dmcfreq->dev, "failed to register panic nb\n"); + dmc_mdevp.data = dmcfreq->info.devfreq; dmcfreq->mdev_info = rockchip_system_monitor_register(dmcfreq->dev, &dmc_mdevp); diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 2c50c0e57215..4a50b4a6a347 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -1728,6 +1728,48 @@ out: } EXPORT_SYMBOL(rockchip_init_opp_table); +int rockchip_opp_dump_cur_state(struct device *dev) +{ + struct clk *clk; + struct opp_table *opp_table; + int volt_vdd, volt_mem; + + if (!dev) + return -ENODEV; + + opp_table = dev_pm_opp_get_opp_table(dev); + if (IS_ERR(opp_table)) { + dev_err(dev, "%s: device opp doesn't exist\n", __func__); + return PTR_ERR(opp_table); + } + + clk = opp_table->clk; + if (IS_ERR(clk)) { + dev_err(dev, "%s: No clock available for the device\n", + __func__); + dev_pm_opp_put_opp_table(opp_table); + return PTR_ERR(clk); + } + + if (opp_table->regulator_count == 1) { + volt_vdd = regulator_get_voltage(opp_table->regulators[0]); + dev_info(dev, "cur_freq: %lu Hz, volt: %d uV\n", + clk_get_rate(clk), volt_vdd); + } + + if (opp_table->regulator_count == 2) { + volt_vdd = regulator_get_voltage(opp_table->regulators[0]); + volt_mem = regulator_get_voltage(opp_table->regulators[1]); + dev_info(dev, "cur_freq: %lu Hz, volt_vdd: %d uV, volt_mem: %d uV\n", + clk_get_rate(clk), volt_vdd, volt_mem); + } + + dev_pm_opp_put_opp_table(opp_table); + + return 0; +} +EXPORT_SYMBOL(rockchip_opp_dump_cur_state); + MODULE_DESCRIPTION("ROCKCHIP OPP Select"); MODULE_AUTHOR("Finley Xiao , Liang Chen "); MODULE_LICENSE("GPL"); diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index da9cab568295..35353d8ade6d 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -107,6 +107,7 @@ int rockchip_set_intermediate_rate(struct device *dev, int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, char *lkg_name, char *reg_name); +int rockchip_opp_dump_cur_state(struct device *dev); #else static inline int rockchip_of_get_leakage(struct device *dev, char *lkg_name, int *leakage) @@ -226,6 +227,11 @@ static inline int rockchip_init_opp_table(struct device *dev, return -EOPNOTSUPP; } +static inline int rockchip_opp_dump_cur_state(struct device *dev) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_ROCKCHIP_OPP */ #endif