summaryrefslogtreecommitdiff
path: root/drivers/interconnect
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/interconnect')
-rw-r--r--drivers/interconnect/qcom/icc-rpm-clocks.c6
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c76
-rw-r--r--drivers/interconnect/qcom/icc-rpm.h15
-rw-r--r--drivers/interconnect/qcom/msm8996.c8
-rw-r--r--drivers/interconnect/qcom/qcm2290.c9
-rw-r--r--drivers/interconnect/qcom/qdu1000.c1
-rw-r--r--drivers/interconnect/qcom/sc7180.c1
-rw-r--r--drivers/interconnect/qcom/sc7280.c1
-rw-r--r--drivers/interconnect/qcom/sc8180x.c1
-rw-r--r--drivers/interconnect/qcom/sc8280xp.c1
-rw-r--r--drivers/interconnect/qcom/sdm660.c4
-rw-r--r--drivers/interconnect/qcom/sdm670.c1
-rw-r--r--drivers/interconnect/qcom/sdm845.c1
-rw-r--r--drivers/interconnect/qcom/sm6350.c1
-rw-r--r--drivers/interconnect/qcom/sm8150.c1
-rw-r--r--drivers/interconnect/qcom/sm8250.c1
-rw-r--r--drivers/interconnect/qcom/sm8350.c1
17 files changed, 114 insertions, 15 deletions
diff --git a/drivers/interconnect/qcom/icc-rpm-clocks.c b/drivers/interconnect/qcom/icc-rpm-clocks.c
index 63c82a91bbc7..ac1677de7dfd 100644
--- a/drivers/interconnect/qcom/icc-rpm-clocks.c
+++ b/drivers/interconnect/qcom/icc-rpm-clocks.c
@@ -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,
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 2c16917ba1fd..9c40314e03b5 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -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 @@ regmap_done:
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);
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index eed3451af3e6..a13768cfd231 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -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;
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 88683dfa468f..b73566c9b21f 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -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[] = {
diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c
index 5bc4b7516608..b88cf9a022e0 100644
--- a/drivers/interconnect/qcom/qcm2290.c
+++ b/drivers/interconnect/qcom/qcm2290.c
@@ -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[] = {
diff --git a/drivers/interconnect/qcom/qdu1000.c b/drivers/interconnect/qcom/qdu1000.c
index bf800dd7d4ba..a7392eb73d4a 100644
--- a/drivers/interconnect/qcom/qdu1000.c
+++ b/drivers/interconnect/qcom/qdu1000.c
@@ -769,6 +769,7 @@ static struct qcom_icc_node xs_sys_tcu_cfg = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.num_nodes = 1,
.nodes = { &ebi },
};
diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c
index d94ab9b39f3d..af2be1543840 100644
--- a/drivers/interconnect/qcom/sc7180.c
+++ b/drivers/interconnect/qcom/sc7180.c
@@ -1238,6 +1238,7 @@ static struct qcom_icc_node xs_sys_tcu_cfg = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },
diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c
index 6592839b4d94..a626dbc71999 100644
--- a/drivers/interconnect/qcom/sc7280.c
+++ b/drivers/interconnect/qcom/sc7280.c
@@ -1285,6 +1285,7 @@ static struct qcom_icc_node srvc_snoc = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.num_nodes = 1,
.nodes = { &ebi },
};
diff --git a/drivers/interconnect/qcom/sc8180x.c b/drivers/interconnect/qcom/sc8180x.c
index 0fb4898dabcf..bdd3471d4ac8 100644
--- a/drivers/interconnect/qcom/sc8180x.c
+++ b/drivers/interconnect/qcom/sc8180x.c
@@ -1345,6 +1345,7 @@ static struct qcom_icc_node slv_qup_core_2 = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.num_nodes = 1,
.nodes = { &slv_ebi }
};
diff --git a/drivers/interconnect/qcom/sc8280xp.c b/drivers/interconnect/qcom/sc8280xp.c
index b82c5493cbb5..0270f6c64481 100644
--- a/drivers/interconnect/qcom/sc8280xp.c
+++ b/drivers/interconnect/qcom/sc8280xp.c
@@ -1712,6 +1712,7 @@ static struct qcom_icc_node srvc_snoc = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.num_nodes = 1,
.nodes = { &ebi },
};
diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index 36962f7bd7bb..7392bebba334 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -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[] = {
diff --git a/drivers/interconnect/qcom/sdm670.c b/drivers/interconnect/qcom/sdm670.c
index 540a2108b77c..907e1ff4ff81 100644
--- a/drivers/interconnect/qcom/sdm670.c
+++ b/drivers/interconnect/qcom/sdm670.c
@@ -1047,6 +1047,7 @@ static struct qcom_icc_node xs_sys_tcu_cfg = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index b9243c0aa626..855802be93fe 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -1265,6 +1265,7 @@ static struct qcom_icc_node xs_sys_tcu_cfg = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },
diff --git a/drivers/interconnect/qcom/sm6350.c b/drivers/interconnect/qcom/sm6350.c
index 49aed492e9b8..f41d7e19ba26 100644
--- a/drivers/interconnect/qcom/sm6350.c
+++ b/drivers/interconnect/qcom/sm6350.c
@@ -1164,6 +1164,7 @@ static struct qcom_icc_node xs_sys_tcu_cfg = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },
diff --git a/drivers/interconnect/qcom/sm8150.c b/drivers/interconnect/qcom/sm8150.c
index c7c9cf7f746b..edfe824cad35 100644
--- a/drivers/interconnect/qcom/sm8150.c
+++ b/drivers/interconnect/qcom/sm8150.c
@@ -1282,6 +1282,7 @@ static struct qcom_icc_node xs_sys_tcu_cfg = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },
diff --git a/drivers/interconnect/qcom/sm8250.c b/drivers/interconnect/qcom/sm8250.c
index d4a4ecef11f0..661dc18d99db 100644
--- a/drivers/interconnect/qcom/sm8250.c
+++ b/drivers/interconnect/qcom/sm8250.c
@@ -1397,6 +1397,7 @@ static struct qcom_icc_node qup2_core_slave = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },
diff --git a/drivers/interconnect/qcom/sm8350.c b/drivers/interconnect/qcom/sm8350.c
index bdf75839e6d1..562322d4fc3c 100644
--- a/drivers/interconnect/qcom/sm8350.c
+++ b/drivers/interconnect/qcom/sm8350.c
@@ -1356,6 +1356,7 @@ static struct qcom_icc_node qns_mem_noc_sf_disp = {
static struct qcom_icc_bcm bcm_acv = {
.name = "ACV",
+ .enable_mask = BIT(3),
.keepalive = false,
.num_nodes = 1,
.nodes = { &ebi },