From 40d225830ebd0c1843493820e9362e7406a70b1e Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Wed, 26 Aug 2020 12:18:26 +0530 Subject: [PATCH] interconnect: qcom: Add QoS config support for BIMC masters Introduce support to initialize QoS settings for BIMC masters. Change-Id: Ia225afedb08cb3b09094bc8f4ebd6d12ad9c6a33 Signed-off-by: Odelu Kukatla --- drivers/interconnect/qcom/icc-rpm.c | 20 +++++++ drivers/interconnect/qcom/icc-rpm.h | 4 ++ drivers/interconnect/qcom/qnoc-qos.c | 79 ++++++++++++++++++++++++++-- drivers/interconnect/qcom/qnoc-qos.h | 14 +++++ 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c index 68ce1b375f8f..f607d9877e1a 100644 --- a/drivers/interconnect/qcom/icc-rpm.c +++ b/drivers/interconnect/qcom/icc-rpm.c @@ -15,6 +15,7 @@ #include #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); diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h index 7b1e89c7e077..4849e616fe4b 100644 --- a/drivers/interconnect/qcom/icc-rpm.h +++ b/drivers/interconnect/qcom/icc-rpm.h @@ -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; diff --git a/drivers/interconnect/qcom/qnoc-qos.c b/drivers/interconnect/qcom/qnoc-qos.c index cf78e497e743..4e9d0fa6cbdd 100644 --- a/drivers/interconnect/qcom/qnoc-qos.c +++ b/drivers/interconnect/qcom/qnoc-qos.c @@ -8,7 +8,11 @@ #include #include +#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); + 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"); diff --git a/drivers/interconnect/qcom/qnoc-qos.h b/drivers/interconnect/qcom/qnoc-qos.h index 0c55c95f36a4..38d143981784 100644 --- a/drivers/interconnect/qcom/qnoc-qos.h +++ b/drivers/interconnect/qcom/qnoc-qos.h @@ -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