From b89dc2a89136d72c5fa14ed13f583367cfecdd14 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 16 Jan 2019 20:20:33 -0800 Subject: [PATCH] PM / devfreq: bw_hwmon: Add support for specifying count factor Not all bandwidth monitors count in units of 1MB. Add a DT property that indicates the number of bytes the monitor counts in so we can properly scale the count we read from the hardware to reflect the traffic. By default, we will assume 1MB units if the property doesn't exist. Change-Id: I1b581b2fffda04ba151df6e87221628368ff5b17 Signed-off-by: Stephen Boyd [avajid@codeaurora.org: made minor styling changes] Signed-off-by: Amir Vajid --- drivers/devfreq/bimc-bwmon.c | 39 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c index 34ec734f3317..0937cdf6c822 100644 --- a/drivers/devfreq/bimc-bwmon.c +++ b/drivers/devfreq/bimc-bwmon.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "governor_bw_hwmon.h" #define GLB_INT_STATUS(m) ((m)->global_base + 0x100) @@ -96,6 +98,8 @@ struct bwmon { u32 throttle_adj; u32 sample_size_ms; u32 intr_status; + u8 count_shift; + u32 thres_lim; u32 byte_mask; u32 byte_match; }; @@ -410,11 +414,18 @@ static u32 calc_zone_counts(struct bw_hwmon *hw) return zone_counts; } -static unsigned int mbps_to_mb(unsigned long mbps, unsigned int ms) +#define MB_SHIFT 20 + +static u32 mbps_to_count(unsigned long mbps, unsigned int ms, u8 shift) { mbps *= ms; - mbps = DIV_ROUND_UP(mbps, MSEC_PER_SEC); - return mbps; + + if (shift > MB_SHIFT) + mbps >>= shift - MB_SHIFT; + else + mbps <<= MB_SHIFT - shift; + + return DIV_ROUND_UP(mbps, MSEC_PER_SEC); } /* @@ -422,9 +433,10 @@ static unsigned int mbps_to_mb(unsigned long mbps, unsigned int ms) * Zone 0: byte count < THRES_LO * Zone 1: THRES_LO < byte count < THRES_MED * Zone 2: THRES_MED < byte count < THRES_HI - * Zone 3: byte count > THRES_HI + * Zone 3: THRES_LIM > byte count > THRES_HI */ -#define THRES_LIM 0x7FFU +#define THRES_LIM(shift) (0xFFFFFFFF >> shift) + static __always_inline void set_zone_thres(struct bwmon *m, unsigned int sample_ms, enum mon_reg_type type) @@ -433,14 +445,14 @@ void set_zone_thres(struct bwmon *m, unsigned int sample_ms, u32 hi, med, lo; u32 zone_cnt_thres = calc_zone_counts(hw); - hi = mbps_to_mb(hw->up_wake_mbps, sample_ms); - med = mbps_to_mb(hw->down_wake_mbps, sample_ms); + hi = mbps_to_count(hw->up_wake_mbps, sample_ms, m->count_shift); + med = mbps_to_count(hw->down_wake_mbps, sample_ms, m->count_shift); lo = 0; - if (unlikely((hi > THRES_LIM) || (med > hi) || (lo > med))) { + if (unlikely((hi > m->thres_lim) || (med > hi) || (lo > med))) { pr_warn("Zone thres larger than hw limit: hi:%u med:%u lo:%u\n", hi, med, lo); - hi = min(hi, THRES_LIM); + hi = min(hi, m->thres_lim); med = min(med, hi - 1); lo = min(lo, med-1); } @@ -572,7 +584,7 @@ unsigned long mon_get_zone_stats(struct bwmon *m, enum mon_reg_type type) zone = get_zone(m, type); count = get_zone_count(m, zone, type); - count *= SZ_1M; + count <<= m->count_shift; dev_dbg(m->dev, "Zone%d Max byte count: %08lx\n", zone, count); @@ -984,7 +996,7 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) struct resource *res; struct bwmon *m; int ret; - u32 data; + u32 data, count_unit; m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL); if (!m) @@ -1049,6 +1061,11 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) } } + if (of_property_read_u32(dev->of_node, "qcom,count-unit", &count_unit)) + count_unit = SZ_1M; + m->count_shift = order_base_2(count_unit); + m->thres_lim = THRES_LIM(m->count_shift); + switch (m->spec->reg_type) { case MON3: m->hw.start_hwmon = start_bw_hwmon3;