diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c index b27fe0b488e1..c37955a274d0 100644 --- a/drivers/clk/qcom/clk-debug.c +++ b/drivers/clk/qcom/clk-debug.c @@ -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); }