From 5725b8dbe768ee08243586dfb677d1c6dd12195a Mon Sep 17 00:00:00 2001 From: David Dai Date: Fri, 13 Jul 2018 18:20:02 -0700 Subject: [PATCH] clk: qcom: clk-debug: Add custom measure operators for mccc_clk Since the generic way of using testclock to measure ddr mc clock is not available, rely on reading the period of the current mc clock frequency written to by DDRSS software. This does not provide the physical rate at which the clock is running, but a snapshot of the current configuration. Change-Id: I37ce2927be7712adc2b722ed0a26c8eaf4596dd2 Signed-off-by: David Dai --- drivers/clk/qcom/clk-debug.c | 46 +++++++++++++++++++++++++++++++++++- drivers/clk/qcom/clk-debug.h | 4 ++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c index b9d3d717ebef..76982b79a804 100644 --- a/drivers/clk/qcom/clk-debug.c +++ b/drivers/clk/qcom/clk-debug.c @@ -297,15 +297,54 @@ exit: DEFINE_SIMPLE_ATTRIBUTE(clk_measure_fops, clk_debug_measure_get, NULL, "%lld\n"); +static int clk_debug_read_period(void *data, u64 *val) +{ + struct clk_hw *hw = data; + struct clk_debug_mux *meas = to_clk_measure(measure); + int index; + int dbg_cc; + int ret = 0; + u32 regval; + + mutex_lock(&clk_debug_lock); + + ret = clk_set_parent(measure->clk, hw->clk); + if (!ret) { + index = clk_debug_mux_get_parent(measure); + dbg_cc = meas->parent[index].dbg_cc; + + regmap_read(meas->regmap[dbg_cc], meas->period_offset, ®val); + if (!regval) { + pr_err("Error reading mccc period register, ret = %d\n", + ret); + mutex_unlock(&clk_debug_lock); + return 0; + } + *val = 1000000000000UL; + do_div(*val, regval); + } else { + pr_err("Failed to set the debug mux's parent.\n"); + } + + mutex_unlock(&clk_debug_lock); + return ret; +} + +DEFINE_SIMPLE_ATTRIBUTE(clk_read_period_fops, clk_debug_read_period, + NULL, "%lld\n"); + int clk_debug_measure_add(struct clk_hw *hw, struct dentry *dentry) { int ret; + int index; + struct clk_debug_mux *meas; if (IS_ERR_OR_NULL(measure)) { pr_err_once("Please check if `measure` clk is registered.\n"); return 0; } + meas = to_clk_measure(measure); ret = clk_set_parent(measure->clk, hw->clk); if (ret) { pr_debug("Unable to set %s as %s's parent, ret=%d\n", @@ -313,7 +352,12 @@ int clk_debug_measure_add(struct clk_hw *hw, struct dentry *dentry) return 0; } - debugfs_create_file("clk_measure", 0444, dentry, hw, + index = clk_debug_mux_get_parent(measure); + if (meas->parent[index].dbg_cc == MC_CC) + debugfs_create_file("clk_measure", 0444, dentry, hw, + &clk_read_period_fops); + else + debugfs_create_file("clk_measure", 0444, dentry, hw, &clk_measure_fops); return 0; } diff --git a/drivers/clk/qcom/clk-debug.h b/drivers/clk/qcom/clk-debug.h index 742c295e43f0..ba25ee611819 100644 --- a/drivers/clk/qcom/clk-debug.h +++ b/drivers/clk/qcom/clk-debug.h @@ -45,6 +45,7 @@ enum debug_cc { GPU_CC, VIDEO_CC, CPU_CC, + MC_CC, MAX_NUM_CC, }; @@ -111,6 +112,8 @@ struct clk_src { mux. * @post_div_shift: indicates the shift required for post divider selection in primary mux. + * @period_offset: offset of the period register used to read to determine + the mc clock period * @hw: handle between common and hardware-specific interfaces. */ struct clk_debug_mux { @@ -126,6 +129,7 @@ struct clk_debug_mux { u32 src_sel_shift; u32 post_div_mask; u32 post_div_shift; + u32 period_offset; struct clk_hw hw; };