Skip to content

Commit 1400725

Browse files
author
Georgi Djakov
committed
Merge branch 'icc-qos' into icc-next
* icc-qos interconnect: qcom: rpm: Rename icc desc clocks to bus_blocks interconnect: qcom: rpm: Rename icc provider num_clocks to num_bus_clocks interconnect: qcom: rpm: Drop unused parameters interconnect: qcom: rpm: Set QoS registers only once interconnect: qcom: rpm: Handle interface clocks interconnect: qcom: icc-rpm: Enforce 2 or 0 bus clocks interconnect: qcom: rpm: Don't use clk_get_optional for bus clocks anymore interconnect: qcom: msm8996: Promote to core_initcall interconnect: qcom: rpm: allocate enough data in probe() Link: https://lore.kernel.org/r/20230228-topic-qos-v8-0-ee696a2c15a9@linaro.org Signed-off-by: Georgi Djakov <djakov@kernel.org>
2 parents 7f1ed46 + 0ebee0a commit 1400725

4 files changed

Lines changed: 103 additions & 83 deletions

File tree

drivers/interconnect/qcom/icc-rpm.c

Lines changed: 59 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
#define NOC_QOS_MODE_FIXED_VAL 0x0
5151
#define NOC_QOS_MODE_BYPASS_VAL 0x2
5252

53-
static int qcom_icc_set_qnoc_qos(struct icc_node *src, u64 max_bw)
53+
static int qcom_icc_set_qnoc_qos(struct icc_node *src)
5454
{
5555
struct icc_provider *provider = src->provider;
5656
struct qcom_icc_provider *qp = to_qcom_provider(provider);
@@ -95,7 +95,7 @@ static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp,
9595
mask, val);
9696
}
9797

98-
static int qcom_icc_set_bimc_qos(struct icc_node *src, u64 max_bw)
98+
static int qcom_icc_set_bimc_qos(struct icc_node *src)
9999
{
100100
struct qcom_icc_provider *qp;
101101
struct qcom_icc_node *qn;
@@ -150,7 +150,7 @@ static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp,
150150
NOC_QOS_PRIORITY_P0_MASK, qos->prio_level);
151151
}
152152

153-
static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
153+
static int qcom_icc_set_noc_qos(struct icc_node *src)
154154
{
155155
struct qcom_icc_provider *qp;
156156
struct qcom_icc_node *qn;
@@ -187,7 +187,7 @@ static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
187187
NOC_QOS_MODEn_MASK, mode);
188188
}
189189

190-
static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)
190+
static int qcom_icc_qos_set(struct icc_node *node)
191191
{
192192
struct qcom_icc_provider *qp = to_qcom_provider(node->provider);
193193
struct qcom_icc_node *qn = node->data;
@@ -196,65 +196,48 @@ static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)
196196

197197
switch (qp->type) {
198198
case QCOM_ICC_BIMC:
199-
return qcom_icc_set_bimc_qos(node, sum_bw);
199+
return qcom_icc_set_bimc_qos(node);
200200
case QCOM_ICC_QNOC:
201-
return qcom_icc_set_qnoc_qos(node, sum_bw);
201+
return qcom_icc_set_qnoc_qos(node);
202202
default:
203-
return qcom_icc_set_noc_qos(node, sum_bw);
203+
return qcom_icc_set_noc_qos(node);
204204
}
205205
}
206206

207-
static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw)
207+
static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 sum_bw)
208208
{
209209
int ret = 0;
210210

211-
if (mas_rpm_id != -1) {
211+
if (qn->qos.ap_owned)
212+
return 0;
213+
214+
if (qn->mas_rpm_id != -1) {
212215
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
213216
RPM_BUS_MASTER_REQ,
214-
mas_rpm_id,
217+
qn->mas_rpm_id,
215218
sum_bw);
216219
if (ret) {
217220
pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
218-
mas_rpm_id, ret);
221+
qn->mas_rpm_id, ret);
219222
return ret;
220223
}
221224
}
222225

223-
if (slv_rpm_id != -1) {
226+
if (qn->slv_rpm_id != -1) {
224227
ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE,
225228
RPM_BUS_SLAVE_REQ,
226-
slv_rpm_id,
229+
qn->slv_rpm_id,
227230
sum_bw);
228231
if (ret) {
229232
pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
230-
slv_rpm_id, ret);
233+
qn->slv_rpm_id, ret);
231234
return ret;
232235
}
233236
}
234237

235238
return ret;
236239
}
237240

238-
static int __qcom_icc_set(struct icc_node *n, struct qcom_icc_node *qn,
239-
u64 sum_bw)
240-
{
241-
int ret;
242-
243-
if (!qn->qos.ap_owned) {
244-
/* send bandwidth request message to the RPM processor */
245-
ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw);
246-
if (ret)
247-
return ret;
248-
} else if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID) {
249-
/* set bandwidth directly from the AP */
250-
ret = qcom_icc_qos_set(n, sum_bw);
251-
if (ret)
252-
return ret;
253-
}
254-
255-
return 0;
256-
}
257-
258241
/**
259242
* qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests
260243
* @node: icc node to operate on
@@ -370,16 +353,17 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
370353

371354
sum_bw = icc_units_to_bps(max_agg_avg);
372355

373-
ret = __qcom_icc_set(src, src_qn, sum_bw);
356+
ret = qcom_icc_rpm_set(src_qn, sum_bw);
374357
if (ret)
375358
return ret;
359+
376360
if (dst_qn) {
377-
ret = __qcom_icc_set(dst, dst_qn, sum_bw);
361+
ret = qcom_icc_rpm_set(dst_qn, sum_bw);
378362
if (ret)
379363
return ret;
380364
}
381365

382-
for (i = 0; i < qp->num_clks; i++) {
366+
for (i = 0; i < qp->num_bus_clks; i++) {
383367
/*
384368
* Use WAKE bucket for active clock, otherwise, use SLEEP bucket
385369
* for other clocks. If a platform doesn't set interconnect
@@ -425,7 +409,7 @@ int qnoc_probe(struct platform_device *pdev)
425409
struct qcom_icc_provider *qp;
426410
struct icc_node *node;
427411
size_t num_nodes, i;
428-
const char * const *cds;
412+
const char * const *cds = NULL;
429413
int cd_num;
430414
int ret;
431415

@@ -440,31 +424,34 @@ int qnoc_probe(struct platform_device *pdev)
440424
qnodes = desc->nodes;
441425
num_nodes = desc->num_nodes;
442426

443-
if (desc->num_clocks) {
444-
cds = desc->clocks;
445-
cd_num = desc->num_clocks;
427+
if (desc->num_intf_clocks) {
428+
cds = desc->intf_clocks;
429+
cd_num = desc->num_intf_clocks;
446430
} else {
447-
cds = bus_clocks;
448-
cd_num = ARRAY_SIZE(bus_clocks);
431+
/* 0 intf clocks is perfectly fine */
432+
cd_num = 0;
449433
}
450434

451-
qp = devm_kzalloc(dev, struct_size(qp, bus_clks, cd_num), GFP_KERNEL);
435+
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
452436
if (!qp)
453437
return -ENOMEM;
454438

455-
qp->bus_clk_rate = devm_kcalloc(dev, cd_num, sizeof(*qp->bus_clk_rate),
456-
GFP_KERNEL);
457-
if (!qp->bus_clk_rate)
439+
qp->intf_clks = devm_kcalloc(dev, cd_num, sizeof(*qp->intf_clks), GFP_KERNEL);
440+
if (!qp->intf_clks)
458441
return -ENOMEM;
459442

460443
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
461444
GFP_KERNEL);
462445
if (!data)
463446
return -ENOMEM;
464447

448+
qp->num_intf_clks = cd_num;
465449
for (i = 0; i < cd_num; i++)
466-
qp->bus_clks[i].id = cds[i];
467-
qp->num_clks = cd_num;
450+
qp->intf_clks[i].id = cds[i];
451+
452+
qp->num_bus_clks = desc->no_clk_scaling ? 0 : NUM_BUS_CLKS;
453+
for (i = 0; i < qp->num_bus_clks; i++)
454+
qp->bus_clks[i].id = bus_clocks[i];
468455

469456
qp->type = desc->type;
470457
qp->qos_offset = desc->qos_offset;
@@ -494,11 +481,15 @@ int qnoc_probe(struct platform_device *pdev)
494481
}
495482

496483
regmap_done:
497-
ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks);
484+
ret = devm_clk_bulk_get(dev, qp->num_bus_clks, qp->bus_clks);
485+
if (ret)
486+
return ret;
487+
488+
ret = clk_bulk_prepare_enable(qp->num_bus_clks, qp->bus_clks);
498489
if (ret)
499490
return ret;
500491

501-
ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
492+
ret = devm_clk_bulk_get(dev, qp->num_intf_clks, qp->intf_clks);
502493
if (ret)
503494
return ret;
504495

@@ -512,6 +503,11 @@ int qnoc_probe(struct platform_device *pdev)
512503

513504
icc_provider_init(provider);
514505

506+
/* If this fails, bus accesses will crash the platform! */
507+
ret = clk_bulk_prepare_enable(qp->num_intf_clks, qp->intf_clks);
508+
if (ret)
509+
return ret;
510+
515511
for (i = 0; i < num_nodes; i++) {
516512
size_t j;
517513

@@ -528,10 +524,20 @@ int qnoc_probe(struct platform_device *pdev)
528524
for (j = 0; j < qnodes[i]->num_links; j++)
529525
icc_link_create(node, qnodes[i]->links[j]);
530526

527+
/* Set QoS registers (we only need to do it once, generally) */
528+
if (qnodes[i]->qos.ap_owned &&
529+
qnodes[i]->qos.qos_mode != NOC_QOS_MODE_INVALID) {
530+
ret = qcom_icc_qos_set(node);
531+
if (ret)
532+
return ret;
533+
}
534+
531535
data->nodes[i] = node;
532536
}
533537
data->num_nodes = num_nodes;
534538

539+
clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
540+
535541
ret = icc_provider_register(provider);
536542
if (ret)
537543
goto err_remove_nodes;
@@ -551,7 +557,7 @@ int qnoc_probe(struct platform_device *pdev)
551557
icc_provider_deregister(provider);
552558
err_remove_nodes:
553559
icc_nodes_remove(provider);
554-
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
560+
clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
555561

556562
return ret;
557563
}
@@ -563,7 +569,7 @@ int qnoc_remove(struct platform_device *pdev)
563569

564570
icc_provider_deregister(&qp->provider);
565571
icc_nodes_remove(&qp->provider);
566-
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
572+
clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
567573

568574
return 0;
569575
}

drivers/interconnect/qcom/icc-rpm.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,32 @@ enum qcom_icc_type {
2020
QCOM_ICC_QNOC,
2121
};
2222

23+
#define NUM_BUS_CLKS 2
24+
2325
/**
2426
* struct qcom_icc_provider - Qualcomm specific interconnect provider
2527
* @provider: generic interconnect provider
26-
* @num_clks: the total number of clk_bulk_data entries
28+
* @num_bus_clks: the total number of bus_clks clk_bulk_data entries (0 or 2)
29+
* @num_intf_clks: the total number of intf_clks clk_bulk_data entries
2730
* @type: the ICC provider type
2831
* @regmap: regmap for QoS registers read/write access
2932
* @qos_offset: offset to QoS registers
3033
* @bus_clk_rate: bus clock rate in Hz
3134
* @bus_clks: the clk_bulk_data table of bus clocks
35+
* @intf_clks: a clk_bulk_data array of interface clocks
36+
* @is_on: whether the bus is powered on
3237
*/
3338
struct qcom_icc_provider {
3439
struct icc_provider provider;
35-
int num_clks;
40+
int num_bus_clks;
41+
int num_intf_clks;
3642
enum qcom_icc_type type;
3743
struct regmap *regmap;
3844
unsigned int qos_offset;
39-
u64 *bus_clk_rate;
40-
struct clk_bulk_data bus_clks[];
45+
u64 bus_clk_rate[NUM_BUS_CLKS];
46+
struct clk_bulk_data bus_clks[NUM_BUS_CLKS];
47+
struct clk_bulk_data *intf_clks;
48+
bool is_on;
4149
};
4250

4351
/**
@@ -91,8 +99,10 @@ struct qcom_icc_node {
9199
struct qcom_icc_desc {
92100
struct qcom_icc_node * const *nodes;
93101
size_t num_nodes;
94-
const char * const *clocks;
95-
size_t num_clocks;
102+
const char * const *bus_clocks;
103+
const char * const *intf_clocks;
104+
size_t num_intf_clocks;
105+
bool no_clk_scaling;
96106
enum qcom_icc_type type;
97107
const struct regmap_config *regmap_cfg;
98108
unsigned int qos_offset;

drivers/interconnect/qcom/msm8996.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,17 @@
2121
#include "smd-rpm.h"
2222
#include "msm8996.h"
2323

24-
static const char * const bus_mm_clocks[] = {
25-
"bus",
26-
"bus_a",
24+
static const char * const mm_intf_clocks[] = {
2725
"iface"
2826
};
2927

30-
static const char * const bus_a0noc_clocks[] = {
28+
static const char * const a0noc_intf_clocks[] = {
3129
"aggre0_snoc_axi",
3230
"aggre0_cnoc_ahb",
3331
"aggre0_noc_mpu_cfg"
3432
};
3533

36-
static const char * const bus_a2noc_clocks[] = {
37-
"bus",
38-
"bus_a",
34+
static const char * const a2noc_intf_clocks[] = {
3935
"aggre2_ufs_axi",
4036
"ufs_axi"
4137
};
@@ -1821,8 +1817,9 @@ static const struct qcom_icc_desc msm8996_a0noc = {
18211817
.type = QCOM_ICC_NOC,
18221818
.nodes = a0noc_nodes,
18231819
.num_nodes = ARRAY_SIZE(a0noc_nodes),
1824-
.clocks = bus_a0noc_clocks,
1825-
.num_clocks = ARRAY_SIZE(bus_a0noc_clocks),
1820+
.intf_clocks = a0noc_intf_clocks,
1821+
.num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
1822+
.no_clk_scaling = true,
18261823
.regmap_cfg = &msm8996_a0noc_regmap_config
18271824
};
18281825

@@ -1865,8 +1862,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
18651862
.type = QCOM_ICC_NOC,
18661863
.nodes = a2noc_nodes,
18671864
.num_nodes = ARRAY_SIZE(a2noc_nodes),
1868-
.clocks = bus_a2noc_clocks,
1869-
.num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
1865+
.intf_clocks = a2noc_intf_clocks,
1866+
.num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
18701867
.regmap_cfg = &msm8996_a2noc_regmap_config
18711868
};
18721869

@@ -2004,8 +2001,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
20042001
.type = QCOM_ICC_NOC,
20052002
.nodes = mnoc_nodes,
20062003
.num_nodes = ARRAY_SIZE(mnoc_nodes),
2007-
.clocks = bus_mm_clocks,
2008-
.num_clocks = ARRAY_SIZE(bus_mm_clocks),
2004+
.intf_clocks = mm_intf_clocks,
2005+
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
20092006
.regmap_cfg = &msm8996_mnoc_regmap_config
20102007
};
20112008

@@ -2111,7 +2108,17 @@ static struct platform_driver qnoc_driver = {
21112108
.sync_state = icc_sync_state,
21122109
}
21132110
};
2114-
module_platform_driver(qnoc_driver);
2111+
static int __init qnoc_driver_init(void)
2112+
{
2113+
return platform_driver_register(&qnoc_driver);
2114+
}
2115+
core_initcall(qnoc_driver_init);
2116+
2117+
static void __exit qnoc_driver_exit(void)
2118+
{
2119+
platform_driver_unregister(&qnoc_driver);
2120+
}
2121+
module_exit(qnoc_driver_exit);
21152122

21162123
MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
21172124
MODULE_DESCRIPTION("Qualcomm MSM8996 NoC driver");

0 commit comments

Comments
 (0)