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

Commit 6a0e7c24 authored by Rama Aparna Mallavarapu's avatar Rama Aparna Mallavarapu
Browse files

PM / devfreq: bimc-bwmon: Add support for version 2



The version 2 of the BIMC BWMON HW doesn't reset the counter to 0 when it
hits the threshold. It also has support for an overflow status register.

Change-Id: I9f18d2153a2e5e762ec9950f26e0e7601468a80a
Signed-off-by: default avatarSaravana Kannan <skannan@codeaurora.org>
Signed-off-by: default avatarRama Aparna Mallavarapu <aparnam@codeaurora.org>
parent b4ec3a14
Loading
Loading
Loading
Loading
+48 −13
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spinlock.h>
#include "governor_bw_hwmon.h"

@@ -31,11 +32,17 @@
#define MON_MASK(m)		((m)->base + 0x298)
#define MON_MATCH(m)		((m)->base + 0x29C)

struct bwmon_spec {
	bool wrap_on_thres;
	bool overflow;
};

struct bwmon {
	void __iomem *base;
	void __iomem *global_base;
	unsigned int mport;
	unsigned int irq;
	const struct bwmon_spec *spec;
	struct device *dev;
	struct bw_hwmon hw;
};
@@ -94,7 +101,7 @@ static void mon_irq_disable(struct bwmon *m)
	writel_relaxed(val, MON_INT_EN(m));
}

static int mon_irq_status(struct bwmon *m)
static unsigned int mon_irq_status(struct bwmon *m)
{
	u32 mval;

@@ -103,12 +110,12 @@ static int mon_irq_status(struct bwmon *m)
	dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
			readl_relaxed(GLB_INT_STATUS(m)));

	return mval & 0x1;
	return mval;
}

static void mon_irq_clear(struct bwmon *m)
{
	writel_relaxed(0x1, MON_INT_CLR(m));
	writel_relaxed(0x3, MON_INT_CLR(m));
	/* Ensure the monitor IRQ is clear before clearing GLB IRQ */
	mb();
	writel_relaxed(1 << m->mport, GLB_INT_CLR(m));
@@ -127,14 +134,22 @@ static u32 mon_get_limit(struct bwmon *m)
	return readl_relaxed(MON_THRES(m));
}

#define THRES_HIT(status)	(status & BIT(0))
#define OVERFLOW(status)	(status & BIT(1))
static unsigned long mon_get_count(struct bwmon *m)
{
	unsigned long count;
	unsigned long count, status;

	count = readl_relaxed(MON_CNT(m));
	status = mon_irq_status(m);

	dev_dbg(m->dev, "Counter: %08lx\n", count);
	if (mon_irq_status(m))

	if (OVERFLOW(status) && m->spec->overflow)
		count += 0xFFFFFFFF;
	if (THRES_HIT(status) && m->spec->wrap_on_thres)
		count += mon_get_limit(m);

	dev_dbg(m->dev, "Actual Count: %08lx\n", count);

	return count;
@@ -173,11 +188,17 @@ static unsigned long meas_bw_and_set_irq(struct bw_hwmon *hw,

	mbps = mon_get_count(m);
	mbps = bytes_to_mbps(mbps, us);

	/*
	 * The fudging of mbps when calculating limit is to workaround a HW
	 * design issue. Needs further tuning.
	 * If the counter wraps on thres, don't set the thres too low.
	 * Setting it too low runs the risk of the counter wrapping around
	 * multiple times before the IRQ is processed.
	 */
	if (likely(!m->spec->wrap_on_thres))
		limit = mbps_to_bytes(mbps, sample_ms, tol);
	else
		limit = mbps_to_bytes(max(mbps, 400UL), sample_ms, tol);

	mon_set_limit(m, limit);

	mon_clear(m);
@@ -273,11 +294,23 @@ static int resume_bw_hwmon(struct bw_hwmon *hw)

/*************************************************************************/

static const struct bwmon_spec spec[] = {
	{ .wrap_on_thres = true, .overflow = false },
	{ .wrap_on_thres = false, .overflow = true },
};

static const struct of_device_id bimc_bwmon_match_table[] = {
	{ .compatible = "qcom,bimc-bwmon", .data = &spec[0] },
	{ .compatible = "qcom,bimc-bwmon2", .data = &spec[1] },
	{}
};

static int bimc_bwmon_driver_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct bwmon *m;
	const struct of_device_id *id;
	int ret;
	u32 data;

@@ -293,6 +326,13 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev)
	}
	m->mport = data;

	id = of_match_device(bimc_bwmon_match_table, dev);
	if (!id) {
		dev_err(dev, "Unknown device type!\n");
		return -ENODEV;
	}
	m->spec = id->data;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
	if (!res) {
		dev_err(dev, "base not found!\n");
@@ -339,11 +379,6 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev)
	return 0;
}

static const struct of_device_id bimc_bwmon_match_table[] = {
	{ .compatible = "qcom,bimc-bwmon" },
	{}
};

static struct platform_driver bimc_bwmon_driver = {
	.probe = bimc_bwmon_driver_probe,
	.driver = {