The hardware programming guide recommends to clear all registers on first initialization, through separate field in BWMON_CLEAR register. This makes sense in general but especially if driver is rebound to avoid spurious/early interrupts. Cc: Rajendra Nayak <quic_rjendra@xxxxxxxxxxx> Cc: Sibi Sankar <quic_sibis@xxxxxxxxxxx> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@xxxxxxxxxx> --- drivers/soc/qcom/icc-bwmon.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index a820855e85b4..d2df8feff651 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -50,6 +50,7 @@ #define BWMON_CLEAR 0x2a4 #define BWMON_CLEAR_CLEAR BIT(0) +#define BWMON_CLEAR_CLEAR_ALL BIT(1) #define BWMON_SAMPLE_WINDOW 0x2a8 #define BWMON_THRESHOLD_HIGH 0x2ac @@ -127,8 +128,12 @@ struct icc_bwmon { unsigned int current_kbps; }; -static void bwmon_clear_counters(struct icc_bwmon *bwmon) +static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) { + unsigned int val = BWMON_CLEAR_CLEAR; + + if (clear_all) + val |= BWMON_CLEAR_CLEAR_ALL; /* * Clear counters. The order and barriers are * important. Quoting downstream Qualcomm msm-4.9 tree: @@ -137,7 +142,7 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon) * region. So, we need to make sure the counter clear is completed * before we try to clear the IRQ or do any other counter operations. */ - writel(BWMON_CLEAR_CLEAR, bwmon->base + BWMON_CLEAR); + writel(val, bwmon->base + BWMON_CLEAR); } static void bwmon_clear_irq(struct icc_bwmon *bwmon) @@ -208,7 +213,7 @@ static void bwmon_start(struct icc_bwmon *bwmon) unsigned int thres_count; int window; - bwmon_clear_counters(bwmon); + bwmon_clear_counters(bwmon, true); window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); /* Maximum sampling window: 0xfffff */ @@ -304,7 +309,7 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id) bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, up_kbps); bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, down_kbps); /* Write barriers in bwmon_clear_counters() */ - bwmon_clear_counters(bwmon); + bwmon_clear_counters(bwmon, false); bwmon_clear_irq(bwmon); bwmon_enable(bwmon, irq_enable); -- 2.34.1