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 = { ...@@ -25,6 +25,12 @@ const struct rpm_clk_resource bimc_clk = {
}; };
EXPORT_SYMBOL_GPL(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 = { const struct rpm_clk_resource bus_0_clk = {
.resource_type = QCOM_SMD_RPM_BUS_CLK, .resource_type = QCOM_SMD_RPM_BUS_CLK,
.clock_id = 0, .clock_id = 0,
......
...@@ -291,6 +291,32 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, ...@@ -291,6 +291,32 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
return 0; 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 * qcom_icc_bus_aggregate - calculate bus clock rates by traversing all nodes
* @provider: generic interconnect provider * @provider: generic interconnect provider
...@@ -298,10 +324,10 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, ...@@ -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) 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 qcom_icc_node *qn;
struct icc_node *node; struct icc_node *node;
int i; int ctx;
/* /*
* Iterate nodes on the provider, aggregate bandwidth requests for * 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 ...@@ -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) { list_for_each_entry(node, &provider->nodes, node_list) {
qn = node->data; qn = node->data;
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) { for (ctx = 0; ctx < QCOM_SMD_RPM_STATE_NUM; ctx++) {
if (qn->channels) agg_clk_rate[ctx] = max_t(u64, agg_clk_rate[ctx],
agg_avg_rate = div_u64(qn->sum_avg[i], qn->channels); qcom_icc_calc_rate(qp, qn, ctx));
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);
} }
} }
} }
...@@ -395,6 +414,33 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) ...@@ -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; 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; return 0;
} }
...@@ -517,6 +563,12 @@ int qnoc_probe(struct platform_device *pdev) ...@@ -517,6 +563,12 @@ int qnoc_probe(struct platform_device *pdev)
for (i = 0; i < num_nodes; i++) { for (i = 0; i < num_nodes; i++) {
size_t j; 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); node = icc_node_create(qnodes[i]->id);
if (IS_ERR(node)) { if (IS_ERR(node)) {
ret = PTR_ERR(node); ret = PTR_ERR(node);
......
...@@ -44,6 +44,8 @@ struct rpm_clk_resource { ...@@ -44,6 +44,8 @@ struct rpm_clk_resource {
* @type: the ICC provider type * @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access * @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers * @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_rate: bus clock rate in Hz
* @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks * @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks
* @bus_clk: a pointer to a HLOS-owned bus clock * @bus_clk: a pointer to a HLOS-owned bus clock
...@@ -57,6 +59,8 @@ struct qcom_icc_provider { ...@@ -57,6 +59,8 @@ struct qcom_icc_provider {
enum qcom_icc_type type; enum qcom_icc_type type;
struct regmap *regmap; struct regmap *regmap;
unsigned int qos_offset; unsigned int qos_offset;
u16 ab_coeff;
u16 ib_coeff;
u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM]; u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
const struct rpm_clk_resource *bus_clk_desc; const struct rpm_clk_resource *bus_clk_desc;
struct clk *bus_clk; struct clk *bus_clk;
...@@ -93,11 +97,15 @@ struct qcom_icc_qos { ...@@ -93,11 +97,15 @@ struct qcom_icc_qos {
* @num_links: the total number of @links * @num_links: the total number of @links
* @channels: number of channels at this node (e.g. DDR channels) * @channels: number of channels at this node (e.g. DDR channels)
* @buswidth: width of the interconnect between a node and the bus (bytes) * @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 * @sum_avg: current sum aggregate value of all avg bw requests
* @max_peak: current max aggregate value of all peak bw requests * @max_peak: current max aggregate value of all peak bw requests
* @mas_rpm_id: RPM id for devices that are bus masters * @mas_rpm_id: RPM id for devices that are bus masters
* @slv_rpm_id: RPM id for devices that are bus slaves * @slv_rpm_id: RPM id for devices that are bus slaves
* @qos: NoC QoS setting parameters * @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 { struct qcom_icc_node {
unsigned char *name; unsigned char *name;
...@@ -106,11 +114,15 @@ struct qcom_icc_node { ...@@ -106,11 +114,15 @@ struct qcom_icc_node {
u16 num_links; u16 num_links;
u16 channels; u16 channels;
u16 buswidth; u16 buswidth;
const struct rpm_clk_resource *bus_clk_desc;
u64 sum_avg[QCOM_SMD_RPM_STATE_NUM]; u64 sum_avg[QCOM_SMD_RPM_STATE_NUM];
u64 max_peak[QCOM_SMD_RPM_STATE_NUM]; u64 max_peak[QCOM_SMD_RPM_STATE_NUM];
int mas_rpm_id; int mas_rpm_id;
int slv_rpm_id; int slv_rpm_id;
struct qcom_icc_qos qos; struct qcom_icc_qos qos;
u16 ab_coeff;
u16 ib_coeff;
u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
}; };
struct qcom_icc_desc { struct qcom_icc_desc {
...@@ -123,6 +135,8 @@ struct qcom_icc_desc { ...@@ -123,6 +135,8 @@ struct qcom_icc_desc {
enum qcom_icc_type type; enum qcom_icc_type type;
const struct regmap_config *regmap_cfg; const struct regmap_config *regmap_cfg;
unsigned int qos_offset; unsigned int qos_offset;
u16 ab_coeff;
u16 ib_coeff;
}; };
/* Valid for all bus types */ /* Valid for all bus types */
...@@ -138,6 +152,7 @@ extern const struct rpm_clk_resource bimc_clk; ...@@ -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_0_clk;
extern const struct rpm_clk_resource bus_1_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 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_0_clk;
extern const struct rpm_clk_resource mmaxi_1_clk; extern const struct rpm_clk_resource mmaxi_1_clk;
extern const struct rpm_clk_resource qup_clk; extern const struct rpm_clk_resource qup_clk;
......
...@@ -448,6 +448,7 @@ static struct qcom_icc_node mas_mdp_p0 = { ...@@ -448,6 +448,7 @@ static struct qcom_icc_node mas_mdp_p0 = {
.name = "mas_mdp_p0", .name = "mas_mdp_p0",
.id = MSM8996_MASTER_MDP_PORT0, .id = MSM8996_MASTER_MDP_PORT0,
.buswidth = 32, .buswidth = 32,
.ib_coeff = 25,
.mas_rpm_id = 8, .mas_rpm_id = 8,
.slv_rpm_id = -1, .slv_rpm_id = -1,
.qos.ap_owned = true, .qos.ap_owned = true,
...@@ -463,6 +464,7 @@ static struct qcom_icc_node mas_mdp_p1 = { ...@@ -463,6 +464,7 @@ static struct qcom_icc_node mas_mdp_p1 = {
.name = "mas_mdp_p1", .name = "mas_mdp_p1",
.id = MSM8996_MASTER_MDP_PORT1, .id = MSM8996_MASTER_MDP_PORT1,
.buswidth = 32, .buswidth = 32,
.ib_coeff = 25,
.mas_rpm_id = 61, .mas_rpm_id = 61,
.slv_rpm_id = -1, .slv_rpm_id = -1,
.qos.ap_owned = true, .qos.ap_owned = true,
...@@ -1889,7 +1891,8 @@ static const struct qcom_icc_desc msm8996_bimc = { ...@@ -1889,7 +1891,8 @@ static const struct qcom_icc_desc msm8996_bimc = {
.nodes = bimc_nodes, .nodes = bimc_nodes,
.num_nodes = ARRAY_SIZE(bimc_nodes), .num_nodes = ARRAY_SIZE(bimc_nodes),
.bus_clk_desc = &bimc_clk, .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[] = { static struct qcom_icc_node * const cnoc_nodes[] = {
...@@ -2004,7 +2007,8 @@ static const struct qcom_icc_desc msm8996_mnoc = { ...@@ -2004,7 +2007,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
.bus_clk_desc = &mmaxi_0_clk, .bus_clk_desc = &mmaxi_0_clk,
.intf_clocks = mm_intf_clocks, .intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(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[] = { static struct qcom_icc_node * const pnoc_nodes[] = {
......
...@@ -112,6 +112,9 @@ static struct qcom_icc_node mas_appss_proc = { ...@@ -112,6 +112,9 @@ static struct qcom_icc_node mas_appss_proc = {
.qos.qos_mode = NOC_QOS_MODE_FIXED, .qos.qos_mode = NOC_QOS_MODE_FIXED,
.qos.prio_level = 0, .qos.prio_level = 0,
.qos.areq_prio = 0, .qos.areq_prio = 0,
.bus_clk_desc = &mem_1_clk,
.ab_coeff = 159,
.ib_coeff = 96,
.mas_rpm_id = 0, .mas_rpm_id = 0,
.slv_rpm_id = -1, .slv_rpm_id = -1,
.num_links = ARRAY_SIZE(mas_appss_proc_links), .num_links = ARRAY_SIZE(mas_appss_proc_links),
...@@ -675,7 +678,8 @@ static struct qcom_icc_node mas_gfx3d = { ...@@ -675,7 +678,8 @@ static struct qcom_icc_node mas_gfx3d = {
static struct qcom_icc_node slv_ebi1 = { static struct qcom_icc_node slv_ebi1 = {
.name = "slv_ebi1", .name = "slv_ebi1",
.id = QCM2290_SLAVE_EBI1, .id = QCM2290_SLAVE_EBI1,
.buswidth = 8, .buswidth = 4,
.channels = 2,
.mas_rpm_id = -1, .mas_rpm_id = -1,
.slv_rpm_id = 0, .slv_rpm_id = 0,
}; };
...@@ -1199,6 +1203,7 @@ static const struct qcom_icc_desc qcm2290_bimc = { ...@@ -1199,6 +1203,7 @@ static const struct qcom_icc_desc qcm2290_bimc = {
.keep_alive = true, .keep_alive = true,
/* M_REG_BASE() in vendor msm_bus_bimc_adhoc driver */ /* M_REG_BASE() in vendor msm_bus_bimc_adhoc driver */
.qos_offset = 0x8000, .qos_offset = 0x8000,
.ab_coeff = 153,
}; };
static struct qcom_icc_node * const qcm2290_cnoc_nodes[] = { static struct qcom_icc_node * const qcm2290_cnoc_nodes[] = {
...@@ -1329,6 +1334,7 @@ static const struct qcom_icc_desc qcm2290_mmnrt_virt = { ...@@ -1329,6 +1334,7 @@ static const struct qcom_icc_desc qcm2290_mmnrt_virt = {
.regmap_cfg = &qcm2290_snoc_regmap_config, .regmap_cfg = &qcm2290_snoc_regmap_config,
.keep_alive = true, .keep_alive = true,
.qos_offset = 0x15000, .qos_offset = 0x15000,
.ab_coeff = 142,
}; };
static struct qcom_icc_node * const qcm2290_mmrt_virt_nodes[] = { static struct qcom_icc_node * const qcm2290_mmrt_virt_nodes[] = {
...@@ -1345,6 +1351,7 @@ static const struct qcom_icc_desc qcm2290_mmrt_virt = { ...@@ -1345,6 +1351,7 @@ static const struct qcom_icc_desc qcm2290_mmrt_virt = {
.regmap_cfg = &qcm2290_snoc_regmap_config, .regmap_cfg = &qcm2290_snoc_regmap_config,
.keep_alive = true, .keep_alive = true,
.qos_offset = 0x15000, .qos_offset = 0x15000,
.ab_coeff = 139,
}; };
static const struct of_device_id qcm2290_noc_of_match[] = { static const struct of_device_id qcm2290_noc_of_match[] = {
......
...@@ -602,6 +602,7 @@ static struct qcom_icc_node mas_mdp_p0 = { ...@@ -602,6 +602,7 @@ static struct qcom_icc_node mas_mdp_p0 = {
.name = "mas_mdp_p0", .name = "mas_mdp_p0",
.id = SDM660_MASTER_MDP_P0, .id = SDM660_MASTER_MDP_P0,
.buswidth = 16, .buswidth = 16,
.ib_coeff = 50,
.mas_rpm_id = 8, .mas_rpm_id = 8,
.slv_rpm_id = -1, .slv_rpm_id = -1,
.qos.ap_owned = true, .qos.ap_owned = true,
...@@ -621,6 +622,7 @@ static struct qcom_icc_node mas_mdp_p1 = { ...@@ -621,6 +622,7 @@ static struct qcom_icc_node mas_mdp_p1 = {
.name = "mas_mdp_p1", .name = "mas_mdp_p1",
.id = SDM660_MASTER_MDP_P1, .id = SDM660_MASTER_MDP_P1,
.buswidth = 16, .buswidth = 16,
.ib_coeff = 50,
.mas_rpm_id = 61, .mas_rpm_id = 61,
.slv_rpm_id = -1, .slv_rpm_id = -1,
.qos.ap_owned = true, .qos.ap_owned = true,
...@@ -1540,6 +1542,7 @@ static const struct qcom_icc_desc sdm660_bimc = { ...@@ -1540,6 +1542,7 @@ static const struct qcom_icc_desc sdm660_bimc = {
.num_nodes = ARRAY_SIZE(sdm660_bimc_nodes), .num_nodes = ARRAY_SIZE(sdm660_bimc_nodes),
.bus_clk_desc = &bimc_clk, .bus_clk_desc = &bimc_clk,
.regmap_cfg = &sdm660_bimc_regmap_config, .regmap_cfg = &sdm660_bimc_regmap_config,
.ab_coeff = 153,
}; };
static struct qcom_icc_node * const sdm660_cnoc_nodes[] = { static struct qcom_icc_node * const sdm660_cnoc_nodes[] = {
...@@ -1659,6 +1662,7 @@ static const struct qcom_icc_desc sdm660_mnoc = { ...@@ -1659,6 +1662,7 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.intf_clocks = mm_intf_clocks, .intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks), .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config, .regmap_cfg = &sdm660_mnoc_regmap_config,
.ab_coeff = 153,
}; };
static struct qcom_icc_node * const sdm660_snoc_nodes[] = { 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