mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 21:59:12 -04:00
clk: qcom: clk-debug: Fix clk measurement algorithm
Due to measurement counter does not self-clear reliably, explicitly clearing CLR_CNT in SW instead of relying on self-clear HW sequence. SW/HW CLR_CNT enable and disable sequence requires ~1us delay to allow clearing the count. Increasing sample rate to 27ms to get more accurate measurement for low frequency clocks which allows to keep logic simpler than implementing different logic for higher vs slows clocks with respect to sample rate. Change-Id: I054083358305124406294511b2d03554ee586557 Signed-off-by: Vivek Aknurwar <viveka@codeaurora.org>
This commit is contained in:
parent
b490abfe54
commit
8ea693da82
1 changed files with 31 additions and 19 deletions
|
|
@ -22,10 +22,12 @@ static DEFINE_MUTEX(clk_debug_lock);
|
|||
|
||||
#define TCXO_DIV_4_HZ 4800000
|
||||
#define SAMPLE_TICKS_1_MS 0x1000
|
||||
#define SAMPLE_TICKS_14_MS 0x10000
|
||||
#define SAMPLE_TICKS_27_MS 0x20000
|
||||
|
||||
#define XO_DIV4_CNT_DONE BIT(25)
|
||||
#define CNT_EN BIT(20)
|
||||
#define CLR_CNT BIT(21)
|
||||
#define XO_DIV4_TERM_CNT_MASK GENMASK(19, 0)
|
||||
#define MEASURE_CNT GENMASK(24, 0)
|
||||
#define CBCR_ENA BIT(0)
|
||||
|
||||
|
|
@ -35,19 +37,31 @@ static u32 run_measurement(unsigned int ticks, struct regmap *regmap,
|
|||
{
|
||||
u32 regval;
|
||||
|
||||
/* Stop counters and set the XO4 counter start value. */
|
||||
regmap_write(regmap, ctl_reg, ticks);
|
||||
/*
|
||||
* Clear CNT_EN to bring it to good known state and
|
||||
* set CLK_CNT to clear previous count.
|
||||
*/
|
||||
regmap_update_bits(regmap, ctl_reg, CNT_EN, 0x0);
|
||||
regmap_update_bits(regmap, ctl_reg, CLR_CNT, CLR_CNT);
|
||||
|
||||
regmap_read(regmap, status_reg, ®val);
|
||||
/*
|
||||
* Wait for timer to become ready
|
||||
* Ideally SW should poll for MEASURE_CNT
|
||||
* but since CLR_CNT is not available across targets
|
||||
* add 1 us delay to let CNT clear /
|
||||
* counter will clear within 3 reference cycle of 4.8 MHz.
|
||||
*/
|
||||
udelay(1);
|
||||
|
||||
/* Wait for timer to become ready. */
|
||||
while ((regval & XO_DIV4_CNT_DONE) != 0) {
|
||||
cpu_relax();
|
||||
regmap_read(regmap, status_reg, ®val);
|
||||
}
|
||||
regmap_update_bits(regmap, ctl_reg, CLR_CNT, 0x0);
|
||||
|
||||
/* Run measurement and wait for completion. */
|
||||
regmap_write(regmap, ctl_reg, (CNT_EN|ticks));
|
||||
/*
|
||||
* Run measurement and wait for completion.
|
||||
*/
|
||||
regmap_update_bits(regmap, ctl_reg, XO_DIV4_TERM_CNT_MASK,
|
||||
ticks & XO_DIV4_TERM_CNT_MASK);
|
||||
|
||||
regmap_update_bits(regmap, ctl_reg, CNT_EN, CNT_EN);
|
||||
|
||||
regmap_read(regmap, status_reg, ®val);
|
||||
|
||||
|
|
@ -56,13 +70,11 @@ static u32 run_measurement(unsigned int ticks, struct regmap *regmap,
|
|||
regmap_read(regmap, status_reg, ®val);
|
||||
}
|
||||
|
||||
/* Return measured ticks. */
|
||||
regmap_update_bits(regmap, ctl_reg, CNT_EN, 0x0);
|
||||
|
||||
regmap_read(regmap, status_reg, ®val);
|
||||
regval &= MEASURE_CNT;
|
||||
|
||||
/* Stop the counters */
|
||||
regmap_write(regmap, ctl_reg, ticks);
|
||||
|
||||
return regval;
|
||||
}
|
||||
|
||||
|
|
@ -94,12 +106,12 @@ static unsigned long clk_debug_mux_measure_rate(struct clk_hw *hw)
|
|||
* then the clock must be off.
|
||||
*/
|
||||
|
||||
/* Run a short measurement. (~1 ms) */
|
||||
/* Run a short measurement. (~1ms) */
|
||||
raw_count_short = run_measurement(SAMPLE_TICKS_1_MS, meas->regmap,
|
||||
data->ctl_reg, data->status_reg);
|
||||
|
||||
/* Run a full measurement. (~14 ms) */
|
||||
raw_count_full = run_measurement(SAMPLE_TICKS_14_MS, meas->regmap,
|
||||
/* Run a full measurement. (~27ms) */
|
||||
raw_count_full = run_measurement(SAMPLE_TICKS_27_MS, meas->regmap,
|
||||
data->ctl_reg, data->status_reg);
|
||||
|
||||
gcc_xo4_reg &= ~BIT(0);
|
||||
|
|
@ -111,7 +123,7 @@ static unsigned long clk_debug_mux_measure_rate(struct clk_hw *hw)
|
|||
else {
|
||||
/* Compute rate in Hz. */
|
||||
raw_count_full = ((raw_count_full * 10) + 15) * TCXO_DIV_4_HZ;
|
||||
do_div(raw_count_full, ((SAMPLE_TICKS_14_MS * 10) + 35));
|
||||
do_div(raw_count_full, ((SAMPLE_TICKS_27_MS * 10) + 35));
|
||||
ret = (raw_count_full * multiplier);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue