Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ff38683 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "PM / devfreq: bw_hwmon: Add support for specifying count factor"

parents bb182284 d63ddbd6
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@ Required properties:
- qcom,target-dev:	The DT device that corresponds to this master port
- qcom,hw-timer-hz:	Hardware sampling rate in Hz. This field must be
			specified for "qcom,bimc-bwmon4"
Optional properties:
- qcom,byte-mid-match:  Byte count MID match value
- qcom,byte-mid-mask:   Byte count MID mask value
- qcom,count-unit:     Number of bytes monitor counts in

Example:
	qcom,cpu-bwmon {
		compatible = "qcom,bimc-bwmon";
@@ -26,4 +31,7 @@ Example:
		qcom,mport = <0>;
		qcom,target-dev = <&cpubw>;
		qcom,hw-timer-hz = <19200000>;
		qcom,byte-mid-match = <0x1e00>;
		qcom,byte-mid-mask = <0x1e00>;
		qcom,count-unit = <0x100000>;
	};
+57 −11
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spinlock.h>
#include <linux/log2.h>
#include <linux/sizes.h>
#include "governor_bw_hwmon.h"

#define GLB_INT_STATUS(m)	((m)->global_base + 0x100)
@@ -56,6 +58,8 @@
#define MON3_INT_STATUS_MASK	0x0F
#define MON3_EN(m)		((m)->base + 0x10)
#define MON3_CLEAR(m)		((m)->base + 0x14)
#define MON3_MASK(m)		((m)->base + 0x18)
#define MON3_MATCH(m)		((m)->base + 0x1C)
#define MON3_SW(m)		((m)->base + 0x20)
#define MON3_THRES_HI(m)	((m)->base + 0x24)
#define MON3_THRES_MED(m)	((m)->base + 0x28)
@@ -94,6 +98,10 @@ struct bwmon {
	u32 throttle_adj;
	u32 sample_size_ms;
	u32 intr_status;
	u8 count_shift;
	u32 thres_lim;
	u32 byte_mask;
	u32 byte_match;
};

#define to_bwmon(ptr)		container_of(ptr, struct bwmon, hw)
@@ -406,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);
}

/*
@@ -418,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)
@@ -429,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);
	}
@@ -568,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);

@@ -723,6 +739,25 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev)
	return IRQ_HANDLED;
}

static __always_inline
void mon_set_byte_count_filter(struct bwmon *m, enum mon_reg_type type)
{
	if (!m->byte_mask)
		return;

	switch (type) {
	case MON1:
	case MON2:
		writel_relaxed(m->byte_mask, MON_MASK(m));
		writel_relaxed(m->byte_match, MON_MATCH(m));
		break;
	case MON3:
		writel_relaxed(m->byte_mask, MON3_MASK(m));
		writel_relaxed(m->byte_match, MON3_MATCH(m));
		break;
	}
}

static __always_inline int __start_bw_hwmon(struct bw_hwmon *hw,
		unsigned long mbps, enum mon_reg_type type)
{
@@ -774,6 +809,7 @@ static __always_inline int __start_bw_hwmon(struct bw_hwmon *hw,
		writel_relaxed(zone_actions, MON3_ZONE_ACTIONS(m));
	}

	mon_set_byte_count_filter(m, type);
	mon_irq_clear(m, type);
	mon_irq_enable(m, type);
	mon_enable(m, type);
@@ -960,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)
@@ -1025,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;
@@ -1052,6 +1093,11 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev)
		break;
	}

	of_property_read_u32(dev->of_node, "qcom,byte-mid-match",
			     &m->byte_match);
	of_property_read_u32(dev->of_node, "qcom,byte-mid-mask",
			     &m->byte_mask);

	if (m->spec->throt_adj) {
		m->hw.set_throttle_adj = mon_set_throttle_adj;
		m->hw.get_throttle_adj = mon_get_throttle_adj;