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

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

Merge "interconnect: qcom: Add QoS config support for BIMC masters"

parents 7c4e91c5 40d22583
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/soc/qcom/smd-rpm.h>

#include "icc-rpm.h"
#include "qnoc-qos.h"

static int qcom_icc_rpm_smd_send_msg(int ctx, int rsc_type, int rpm_id, u64 val)
{
@@ -77,6 +78,9 @@ int qcom_icc_rpm_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
		}
	}

	*agg_avg += avg_bw;
	*agg_peak = max_t(u32, *agg_peak, peak_bw);

	qn->dirty = true;

	return 0;
@@ -209,6 +213,22 @@ int qcom_icc_rpm_set(struct icc_node *src, struct icc_node *dst)
		}
	}

	qn = node->data;
	/* Defer setting QoS until the first non-zero bandwidth request. */
	if (qn && qn->qosbox && !qn->qosbox->initialized &&
		(node->avg_bw || node->peak_bw)) {
		ret = clk_bulk_prepare_enable(qp->num_qos_clks, qp->qos_clks);
		if (ret) {
			pr_err("%s: Clock enable failed for node %s\n",
			__func__, node->name);
			return ret;
		}

		qn->noc_ops->set_qos(qn);
		clk_bulk_disable_unprepare(qp->num_qos_clks, qp->qos_clks);
		qn->qosbox->initialized = true;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(qcom_icc_rpm_set);
+4 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ enum qcom_icc_rpm_context {
 * struct qcom_icc_provider - QTI specific interconnect provider
 * @provider: generic interconnect provider
 * @dev: reference to the NoC device
 * @qos_clks: the clk_bulk_data table of QoS clocks
 * @num_qos_clks: the total number of clk_bulk_data entries
 * @bus_clks: the clk_bulk_data table of bus clocks
 * @num_clks: the total number of clk_bulk_data entries
 * @bus_clk_cur_rate: current frequency of bus clock
@@ -57,6 +59,8 @@ struct qcom_icc_provider {
	struct device *dev;
	struct regmap *regmap;
	struct list_head probe_list;
	struct clk_bulk_data *qos_clks;
	int num_qos_clks;
	struct clk_bulk_data *bus_clks;
	int num_clks;
	u32 util_factor;
+76 −3
Original line number Diff line number Diff line
@@ -8,7 +8,11 @@
#include <linux/interconnect-provider.h>
#include <linux/module.h>

#ifdef CONFIG_INTERCONNECT_QCOM_RPMH
#include "icc-rpmh.h"
#else
#include "icc-rpm.h"
#endif
#include "qnoc-qos.h"

#define QOSGEN_MAINCTL_LO(p, qp)	((p)->offsets[qp] + \
@@ -17,6 +21,23 @@
# define QOS_DFLT_PRIO_MASK		0x7
# define QOS_DFLT_PRIO_SHFT		4

#ifndef CONFIG_INTERCONNECT_QCOM_RPMH
#define QOSGEN_M_BKE_HEALTH(p, qp, n)	((p)->offsets[qp] + ((n) * 4) + \
				(p)->regs[QOSGEN_OFF_MPORT_BKE_HEALTH])
#define QOS_PRIOLVL_MASK		0x7
#define QOS_PRIOLVL_SHFT		0x0
#define QOS_AREQPRIO_MASK		0x70
#define QOS_AREQPRIO_SHFT		0x8

#define QOSGEN_M_BKE_EN(p, qp)	((p)->offsets[qp] + \
				(p)->regs[QOSGEN_OFF_MPORT_BKE_EN])

#define QOS_BKE_EN_MASK		0x1
#define QOS_BKE_EN_SHFT		0x0

#define NUM_BKE_HEALTH_LEVELS		4
#endif

const u8 icc_qnoc_qos_regs[][QOSGEN_OFF_MAX_REGS] = {
	[ICC_QNOC_QOSGEN_TYPE_RPMH] = {
		[QOSGEN_OFF_MAINCTL_LO] = 0x8,
@@ -29,6 +50,15 @@ const u8 icc_qnoc_qos_regs[][QOSGEN_OFF_MAX_REGS] = {
};
EXPORT_SYMBOL(icc_qnoc_qos_regs);

#ifndef CONFIG_INTERCONNECT_QCOM_RPMH
const u8 icc_bimc_qos_regs[][QOSGEN_OFF_MAX_REGS] = {
	[ICC_QNOC_QOSGEN_TYPE_RPMH] = {
		[QOSGEN_OFF_MPORT_BKE_EN] = 0x0,
		[QOSGEN_OFF_MPORT_BKE_HEALTH] = 0x40,
	},
};
EXPORT_SYMBOL(icc_bimc_qos_regs);
#endif
/**
 * qcom_icc_set_qos - initialize static QoS configurations
 * @node: qcom icc node to operate on
@@ -49,11 +79,16 @@ static void qcom_icc_set_qos(struct qcom_icc_node *node)
				   QOS_DFLT_PRIO_MASK << QOS_DFLT_PRIO_SHFT,
				   qos->config->prio << QOS_DFLT_PRIO_SHFT);


		if (qos->config->urg_fwd)
			regmap_update_bits(node->regmap,
				QOSGEN_MAINCTL_LO(qos, port),
				QOS_SLV_URG_MSG_EN,
				QOS_SLV_URG_MSG_EN);
		else
			regmap_update_bits(node->regmap,
				QOSGEN_MAINCTL_LO(qos, port),
				QOS_SLV_URG_MSG_EN, 0x0);
	}
}

@@ -62,4 +97,42 @@ const struct qcom_icc_noc_ops qcom_qnoc4_ops = {
};
EXPORT_SYMBOL(qcom_qnoc4_ops);

#ifndef CONFIG_INTERCONNECT_QCOM_RPMH
/**
 * qcom_icc_set_bimc_qos - initialize static QoS configurations
 * @node: qcom icc node to operate on
 */
static void qcom_icc_set_bimc_qos(struct qcom_icc_node *node)
{
	struct qcom_icc_qosbox *qos = node->qosbox;
	int port, i;

	if (!node->regmap)
		return;

	if (!qos)
		return;

	for (port = 0; port < qos->num_ports; port++) {
		for (i = 0; i < NUM_BKE_HEALTH_LEVELS; i++) {
			regmap_update_bits(node->regmap,
				QOSGEN_M_BKE_HEALTH(qos, port, i),
				((qos->config->prio << QOS_PRIOLVL_SHFT) |
				(qos->config->prio << QOS_AREQPRIO_SHFT)),
				(QOS_PRIOLVL_MASK | QOS_AREQPRIO_MASK));
		};

		regmap_update_bits(node->regmap,
			QOSGEN_M_BKE_EN(qos, port),
			qos->config->bke_enable << QOS_BKE_EN_SHFT,
			QOS_BKE_EN_MASK);
	};
}

const struct qcom_icc_noc_ops qcom_bimc_ops = {
	.set_qos = qcom_icc_set_bimc_qos,
};
EXPORT_SYMBOL(qcom_bimc_ops);
#endif

MODULE_LICENSE("GPL v2");
+14 −0
Original line number Diff line number Diff line
@@ -23,6 +23,14 @@ enum {
	QOSGEN_OFF_REGUL0BW_LO,
};

#ifndef CONFIG_INTERCONNECT_QCOM_RPMH
enum {
	QOSGEN_OFF_MPORT_BKE_HEALTH,
	QOSGEN_OFF_MPORT_BKE_EN,
};

extern const u8 icc_bimc_qos_regs[ICC_QNOC_QOS_MAX_TYPE][QOSGEN_OFF_MAX_REGS];
#endif
extern const u8 icc_qnoc_qos_regs[ICC_QNOC_QOS_MAX_TYPE][QOSGEN_OFF_MAX_REGS];

struct qcom_icc_noc_ops {
@@ -32,6 +40,9 @@ struct qcom_icc_noc_ops {
struct qos_config {
	u32 prio;
	u32 urg_fwd;
#ifndef CONFIG_INTERCONNECT_QCOM_RPMH
	u32 bke_enable;
#endif
};

struct qcom_icc_qosbox {
@@ -55,5 +66,8 @@ struct qcom_icc_qosbox {
	}								\

extern const struct qcom_icc_noc_ops qcom_qnoc4_ops;
#ifndef CONFIG_INTERCONNECT_QCOM_RPMH
extern const struct qcom_icc_noc_ops qcom_bimc_ops;
#endif

#endif