mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
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.org Signed-off-by: Georgi Djakov <djakov@kernel.org>
This commit is contained in:
commit
0481107a44
|
|
@ -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[] = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user