soc: qcom: icc-bwmon: clear all registers on init
authorKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Thu, 28 Jul 2022 11:37:42 +0000 (13:37 +0200)
committerBjorn Andersson <bjorn.andersson@linaro.org>
Thu, 18 Aug 2022 19:13:46 +0000 (14:13 -0500)
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@quicinc.com>
Cc: Sibi Sankar <quic_sibis@quicinc.com>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Tested-by: Steev Klimaszewski <steev@kali.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20220728113748.170548-6-krzysztof.kozlowski@linaro.org
drivers/soc/qcom/icc-bwmon.c

index 90c0494de43b0353a27c77a3aaeb280e0f5629b8..da2b68394730f360ec91a17009462c8dd6433730 100644 (file)
@@ -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);