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

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

Merge "dt-bindings: devfreq: Add DT bindings for ARM memlat driver"

parents 976a3550 1cca3bb6
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
ARM CPU memory latency monitor device

arm-memlat-mon is a device that represents the use of the PMU in ARM cores
to measure the parameters for latency driven memory access patterns.

Required properties:
- compatible:			Must be "qcom,arm-memlat-mon"
- qcom,cpulist:			List of CPU phandles to be monitored in a cluster
- qcom,target-dev:		The DT device that corresponds to this master port
- qcom,core-dev-table:		A mapping table of core frequency to a required bandwidth vote at the
				given core frequency.

Optional properties:
- qcom,cachemiss-ev:		The cache miss event that this monitor is supposed to measure.
				Defaults to 0x17 if not specified.
- qcom,inst-ev:			The instruction count event that this monitor is supposed to measure.
				Defaults to 0x08 if not specified.


Example:
	qcom,arm-memlat-mon {
		compatible = "qcom,arm-memlat-mon";
		qcom,cpulist = <&CPU0 &CPU1>;
		qcom,target-dev = <&memlat0>;
		qcom,cachemiss-ev = <0x2A>;
		qcom,inst-ev = <0x08>;
		qcom,core-dev-table =
			<  300000 1525>,
			<  499200 3143>,
			< 1881600 5859>;
	};
+2 −1
Original line number Diff line number Diff line
@@ -5,7 +5,8 @@ can be used to measure the bandwidth of read/write traffic from the BIMC
master ports. For example, the CPU subsystem sits on one BIMC master port.

Required properties:
- compatible:		Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2"
- compatible:		Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" or
			"qcom,bimc-bwmon3"
- reg:			Pairs of physical base addresses and region sizes of
			memory mapped registers.
- reg-names:		Names of the bases for the above registers. Expected
+36 −4
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
struct bwmon_spec {
	bool wrap_on_thres;
	bool overflow;
	bool throt_adj;
};

struct bwmon {
@@ -45,19 +46,24 @@ struct bwmon {
	const struct bwmon_spec *spec;
	struct device *dev;
	struct bw_hwmon hw;
	u32 throttle_adj;
};

#define to_bwmon(ptr)		container_of(ptr, struct bwmon, hw)

#define ENABLE_MASK BIT(0)
#define THROTTLE_MASK 0x1F
#define THROTTLE_SHIFT 16

static DEFINE_SPINLOCK(glb_lock);
static void mon_enable(struct bwmon *m)
{
	writel_relaxed(0x1, MON_EN(m));
	writel_relaxed((ENABLE_MASK | m->throttle_adj), MON_EN(m));
}

static void mon_disable(struct bwmon *m)
{
	writel_relaxed(0x0, MON_EN(m));
	writel_relaxed(m->throttle_adj, MON_EN(m));
	/*
	 * mon_disable() and mon_irq_clear(),
	 * If latter goes first and count happen to trigger irq, we would
@@ -139,6 +145,26 @@ static void mon_irq_clear(struct bwmon *m)
	mb();
}

static int mon_set_throttle_adj(struct bw_hwmon *hw, uint adj)
{
	struct bwmon *m = to_bwmon(hw);

	if (adj > THROTTLE_MASK)
		return -EINVAL;

	adj = (adj & THROTTLE_MASK) << THROTTLE_SHIFT;
	m->throttle_adj = adj;

	return 0;
}

static u32 mon_get_throttle_adj(struct bw_hwmon *hw)
{
	struct bwmon *m = to_bwmon(hw);

	return m->throttle_adj >> THROTTLE_SHIFT;
}

static void mon_set_limit(struct bwmon *m, u32 count)
{
	writel_relaxed(count, MON_THRES(m));
@@ -318,13 +344,15 @@ 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 },
	{ .wrap_on_thres = true, .overflow = false, .throt_adj = false},
	{ .wrap_on_thres = false, .overflow = true, .throt_adj = false},
	{ .wrap_on_thres = false, .overflow = true, .throt_adj = 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] },
	{ .compatible = "qcom,bimc-bwmon3", .data = &spec[2] },
	{}
};

@@ -393,6 +421,10 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev)
	m->hw.resume_hwmon = &resume_bw_hwmon;
	m->hw.get_bytes_and_clear = &get_bytes_and_clear;
	m->hw.set_thres = &set_thres;
	if (m->spec->throt_adj) {
		m->hw.set_throttle_adj = &mon_set_throttle_adj;
		m->hw.get_throttle_adj = &mon_get_throttle_adj;
	}

	ret = register_bw_hwmon(dev, &m->hw);
	if (ret) {
+14 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2015, 2019, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt) "devfreq-simple-dev: " fmt
@@ -147,12 +147,23 @@ static int devfreq_clock_probe(struct platform_device *pdev)
	if (of_property_read_string(dev->of_node, "governor", &gov_name))
		gov_name = "performance";

	if (of_property_read_bool(dev->of_node, "qcom,prepare-clk")) {
		ret = clk_prepare(d->clk);
		if (ret)
			return ret;
	}

	d->df = devfreq_add_device(dev, p, gov_name, NULL);
	if (IS_ERR(d->df))
		return PTR_ERR_OR_ZERO(d->df);
	if (IS_ERR(d->df)) {
		ret = PTR_ERR_OR_ZERO(d->df);
		goto add_err;
	}

	return 0;
add_err:
	if (of_property_read_bool(dev->of_node, "qcom,prepare-clk"))
		clk_unprepare(d->clk);
	return ret;
}

static int devfreq_clock_remove(struct platform_device *pdev)
+41 −0
Original line number Diff line number Diff line
@@ -651,6 +651,46 @@ static int devfreq_bw_hwmon_get_freq(struct devfreq *df,
	return 0;
}

static ssize_t throttle_adj_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct devfreq *df = to_devfreq(dev);
	struct hwmon_node *node = df->data;
	int ret;
	unsigned int val;

	if (!node->hw->set_throttle_adj)
		return -EPERM;

	ret = kstrtouint(buf, 10, &val);
	if (ret)
		return ret;

	ret = node->hw->set_throttle_adj(node->hw, val);

	if (!ret)
		return count;
	else
		return ret;
}

static ssize_t throttle_adj_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	struct devfreq *df = to_devfreq(dev);
	struct hwmon_node *node = df->data;
	unsigned int val;

	if (!node->hw->get_throttle_adj)
		val = 0;
	else
		val = node->hw->get_throttle_adj(node->hw);

	return snprintf(buf, PAGE_SIZE, "%u\n", val);
}

static DEVICE_ATTR_RW(throttle_adj);

gov_attr(guard_band_mbps, 0U, 2000U);
gov_attr(decay_rate, 0U, 100U);
gov_attr(io_percent, 1U, 100U);
@@ -681,6 +721,7 @@ static struct attribute *dev_attr[] = {
	&dev_attr_hyst_length.attr,
	&dev_attr_idle_mbps.attr,
	&dev_attr_mbps_zones.attr,
	&dev_attr_throttle_adj.attr,
	NULL,
};

Loading