Commit 0481107a authored by Georgi Djakov's avatar Georgi Djakov

Merge branch 'icc-qcom-coefficients' into icc-next

Certain platforms require that some buses (or individual nodes) make
some additional changes to the clock rate formula, throwing in some
magic, Qualcomm-defined coefficients, to account for "inefficiencies".

Add the framework for it and utilize it on a couple SoCs.

* icc-qcom-coefficients
  interconnect: qcom: icc-rpm: Add AB/IB calculations coefficients
  interconnect: qcom: icc-rpm: Separate out clock rate calulcations
  interconnect: qcom: icc-rpm: Let nodes drive their own bus clock
  interconnect: qcom: icc-rpm: Check for node-specific rate coefficients
  interconnect: qcom: qcm2290: Hook up MAS_APPS_PROC's bus clock
  interconnecga qcom: qcm2290: Set AB coefficients
  interconnecgg acom: qcm2290: Update EBI channel configuration
  interconnect: qcom: sdm660: Set AB/IB coefficients
  interconnect: qcom: msm8996: Set AB/IB coefficients

Link: https://lore.kernel.org/r/20230726-topic-icc_coeff-v4-0-c04b60caa467@linaro.orgSigned-off-by: default avatarGeorgi Djakov <djakov@kernel.org>
parents 0bb80ecc 1255f23c
......@@ -25,6 +25,12 @@ const struct rpm_clk_resource bimc_clk = {
};
EXPORT_SYMBOL_GPL(bimc_clk);
const struct rpm_clk_resource mem_1_clk = {
.resource_type = QCOM_SMD_RPM_MEM_CLK,
.clock_id = 1,
};
EXPORT_SYMBOL_GPL(mem_1_clk);
const struct rpm_clk_resource bus_0_clk = {
.resource_type = QCOM_SMD_RPM_BUS_CLK,
.clock_id = 0,
......
......@@ -291,6 +291,32 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
return 0;
}
static u64 qcom_icc_calc_rate(struct qcom_icc_provider *qp, struct qcom_icc_node *qn, int ctx)
{
u64 agg_avg_rate, agg_peak_rate, agg_rate;
if (qn->channels)
agg_avg_rate = div_u64(qn->sum_avg[ctx], qn->channels);
else
agg_avg_rate = qn->sum_avg[ctx];
if (qn->ab_coeff) {
agg_avg_rate = agg_avg_rate * qn->ab_coeff;
agg_avg_rate = div_u64(agg_avg_rate, 100);
}
if (qn->ib_coeff) {
agg_peak_rate = qn->max_peak[ctx] * 100;
agg_peak_rate = div_u64(qn->max_peak[ctx], qn->ib_coeff);
} else {
agg_peak_rate = qn->max_peak[ctx];
}
agg_rate = max_t(u64, agg_avg_rate, agg_peak_rate);
return div_u64(agg_rate, qn->buswidth);
}
/**
* qcom_icc_bus_aggregate - calculate bus clock rates by traversing all nodes
* @provider: generic interconnect provider
......@@ -298,10 +324,10 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
*/
static void qcom_icc_bus_aggregate(struct icc_provider *provider, u64 *agg_clk_rate)
{
u64 agg_avg_rate, agg_rate;
struct qcom_icc_provider *qp = to_qcom_provider(provider);
struct qcom_icc_node *qn;
struct icc_node *node;
int i;
int ctx;
/*
* Iterate nodes on the provider, aggregate bandwidth requests for
......@@ -309,16 +335,9 @@ static void qcom_icc_bus_aggregate(struct icc_provider *provider, u64 *agg_clk_r
*/
list_for_each_entry(node, &provider->nodes, node_list) {
qn = node->data;
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
if (qn->channels)
agg_avg_rate = div_u64(qn->sum_avg[i], qn->channels);
else
agg_avg_rate = qn->sum_avg[i];
agg_rate = max_t(u64, agg_avg_rate, qn->max_peak[i]);
do_div(agg_rate, qn->buswidth);
agg_clk_rate[i] = max_t(u64, agg_clk_rate[i], agg_rate);
for (ctx = 0; ctx < QCOM_SMD_RPM_STATE_NUM; ctx++) {
agg_clk_rate[ctx] = max_t(u64, agg_clk_rate[ctx],
qcom_icc_calc_rate(qp, qn, ctx));
}
}
}
......@@ -395,6 +414,33 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
qp->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE] = sleep_rate;
}
/* Handle the node-specific clock */
if (!src_qn->bus_clk_desc)
return 0;
active_rate = qcom_icc_calc_rate(qp, src_qn, QCOM_SMD_RPM_ACTIVE_STATE);
sleep_rate = qcom_icc_calc_rate(qp, src_qn, QCOM_SMD_RPM_SLEEP_STATE);
if (active_rate != src_qn->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE]) {
ret = qcom_icc_rpm_set_bus_rate(src_qn->bus_clk_desc, QCOM_SMD_RPM_ACTIVE_STATE,
active_rate);
if (ret)
return ret;
/* Cache the rate after we've successfully committed it to RPM */
src_qn->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE] = active_rate;
}
if (sleep_rate != src_qn->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE]) {
ret = qcom_icc_rpm_set_bus_rate(src_qn->bus_clk_desc, QCOM_SMD_RPM_SLEEP_STATE,
sleep_rate);
if (ret)
return ret;
/* Cache the rate after we've successfully committed it to RPM */
src_qn->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE] = sleep_rate;
}
return 0;
}
......@@ -517,6 +563,12 @@ int qnoc_probe(struct platform_device *pdev)
for (i = 0; i < num_nodes; i++) {
size_t j;
if (!qnodes[i]->ab_coeff)
qnodes[i]->ab_coeff = qp->ab_coeff;
if (!qnodes[i]->ib_coeff)
qnodes[i]->ib_coeff = qp->ib_coeff;
node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) {
ret = PTR_ERR(node);
......
......@@ -44,6 +44,8 @@ struct rpm_clk_resource {
* @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers
* @ab_coeff: a percentage-based coefficient for compensating the AB calculations
* @ib_coeff: an inverse-percentage-based coefficient for compensating the IB calculations
* @bus_clk_rate: bus clock rate in Hz
* @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks
* @bus_clk: a pointer to a HLOS-owned bus clock
......@@ -57,6 +59,8 @@ struct qcom_icc_provider {
enum qcom_icc_type type;
struct regmap *regmap;
unsigned int qos_offset;
u16 ab_coeff;
u16 ib_coeff;
u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
const struct rpm_clk_resource *bus_clk_desc;
struct clk *bus_clk;
......@@ -93,11 +97,15 @@ struct qcom_icc_qos {
* @num_links: the total number of @links
* @channels: number of channels at this node (e.g. DDR channels)
* @buswidth: width of the interconnect between a node and the bus (bytes)
* @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks
* @sum_avg: current sum aggregate value of all avg bw requests
* @max_peak: current max aggregate value of all peak bw requests
* @mas_rpm_id: RPM id for devices that are bus masters
* @slv_rpm_id: RPM id for devices that are bus slaves
* @qos: NoC QoS setting parameters
* @ab_coeff: a percentage-based coefficient for compensating the AB calculations
* @ib_coeff: an inverse-percentage-based coefficient for compensating the IB calculations
* @bus_clk_rate: a pointer to an array containing bus clock rates in Hz
*/
struct qcom_icc_node {
unsigned char *name;
......@@ -106,11 +114,15 @@ struct qcom_icc_node {
u16 num_links;
u16 channels;
u16 buswidth;
const struct rpm_clk_resource *bus_clk_desc;
u64 sum_avg[QCOM_SMD_RPM_STATE_NUM];
u64 max_peak[QCOM_SMD_RPM_STATE_NUM];
int mas_rpm_id;
int slv_rpm_id;
struct qcom_icc_qos qos;
u16 ab_coeff;
u16 ib_coeff;
u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
};
struct qcom_icc_desc {
......@@ -123,6 +135,8 @@ struct qcom_icc_desc {
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;
unsigned int qos_offset;
u16 ab_coeff;
u16 ib_coeff;
};
/* Valid for all bus types */
......@@ -138,6 +152,7 @@ extern const struct rpm_clk_resource bimc_clk;
extern const struct rpm_clk_resource bus_0_clk;
extern const struct rpm_clk_resource bus_1_clk;
extern const struct rpm_clk_resource bus_2_clk;
extern const struct rpm_clk_resource mem_1_clk;
extern const struct rpm_clk_resource mmaxi_0_clk;
extern const struct rpm_clk_resource mmaxi_1_clk;
extern const struct rpm_clk_resource qup_clk;
......
......@@ -448,6 +448,7 @@ static struct qcom_icc_node mas_mdp_p0 = {
.name = "mas_mdp_p0",
.id = MSM8996_MASTER_MDP_PORT0,
.buswidth = 32,
.ib_coeff = 25,
.mas_rpm_id = 8,
.slv_rpm_id = -1,
.qos.ap_owned = true,
......@@ -463,6 +464,7 @@ static struct qcom_icc_node mas_mdp_p1 = {
.name = "mas_mdp_p1",
.id = MSM8996_MASTER_MDP_PORT1,
.buswidth = 32,
.ib_coeff = 25,
.mas_rpm_id = 61,
.slv_rpm_id = -1,
.qos.ap_owned = true,
......@@ -1889,7 +1891,8 @@ static const struct qcom_icc_desc msm8996_bimc = {
.nodes = bimc_nodes,
.num_nodes = ARRAY_SIZE(bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &msm8996_bimc_regmap_config
.regmap_cfg = &msm8996_bimc_regmap_config,
.ab_coeff = 154,
};
static struct qcom_icc_node * const cnoc_nodes[] = {
......@@ -2004,7 +2007,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
.bus_clk_desc = &mmaxi_0_clk,
.intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &msm8996_mnoc_regmap_config
.regmap_cfg = &msm8996_mnoc_regmap_config,
.ab_coeff = 154,
};
static struct qcom_icc_node * const pnoc_nodes[] = {
......
......@@ -112,6 +112,9 @@ static struct qcom_icc_node mas_appss_proc = {
.qos.qos_mode = NOC_QOS_MODE_FIXED,
.qos.prio_level = 0,
.qos.areq_prio = 0,
.bus_clk_desc = &mem_1_clk,
.ab_coeff = 159,
.ib_coeff = 96,
.mas_rpm_id = 0,
.slv_rpm_id = -1,
.num_links = ARRAY_SIZE(mas_appss_proc_links),
......@@ -675,7 +678,8 @@ static struct qcom_icc_node mas_gfx3d = {
static struct qcom_icc_node slv_ebi1 = {
.name = "slv_ebi1",
.id = QCM2290_SLAVE_EBI1,
.buswidth = 8,
.buswidth = 4,
.channels = 2,
.mas_rpm_id = -1,
.slv_rpm_id = 0,
};
......@@ -1199,6 +1203,7 @@ static const struct qcom_icc_desc qcm2290_bimc = {
.keep_alive = true,
/* M_REG_BASE() in vendor msm_bus_bimc_adhoc driver */
.qos_offset = 0x8000,
.ab_coeff = 153,
};
static struct qcom_icc_node * const qcm2290_cnoc_nodes[] = {
......@@ -1329,6 +1334,7 @@ static const struct qcom_icc_desc qcm2290_mmnrt_virt = {
.regmap_cfg = &qcm2290_snoc_regmap_config,
.keep_alive = true,
.qos_offset = 0x15000,
.ab_coeff = 142,
};
static struct qcom_icc_node * const qcm2290_mmrt_virt_nodes[] = {
......@@ -1345,6 +1351,7 @@ static const struct qcom_icc_desc qcm2290_mmrt_virt = {
.regmap_cfg = &qcm2290_snoc_regmap_config,
.keep_alive = true,
.qos_offset = 0x15000,
.ab_coeff = 139,
};
static const struct of_device_id qcm2290_noc_of_match[] = {
......
......@@ -602,6 +602,7 @@ static struct qcom_icc_node mas_mdp_p0 = {
.name = "mas_mdp_p0",
.id = SDM660_MASTER_MDP_P0,
.buswidth = 16,
.ib_coeff = 50,
.mas_rpm_id = 8,
.slv_rpm_id = -1,
.qos.ap_owned = true,
......@@ -621,6 +622,7 @@ static struct qcom_icc_node mas_mdp_p1 = {
.name = "mas_mdp_p1",
.id = SDM660_MASTER_MDP_P1,
.buswidth = 16,
.ib_coeff = 50,
.mas_rpm_id = 61,
.slv_rpm_id = -1,
.qos.ap_owned = true,
......@@ -1540,6 +1542,7 @@ static const struct qcom_icc_desc sdm660_bimc = {
.num_nodes = ARRAY_SIZE(sdm660_bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &sdm660_bimc_regmap_config,
.ab_coeff = 153,
};
static struct qcom_icc_node * const sdm660_cnoc_nodes[] = {
......@@ -1659,6 +1662,7 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config,
.ab_coeff = 153,
};
static struct qcom_icc_node * const sdm660_snoc_nodes[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment