Skip to content

Commit 2e2113c

Browse files
konradybcioGeorgi Djakov
authored andcommitted
interconnect: qcom: rpm: Handle interface clocks
Some (but not all) providers (or their specific nodes) require specific clocks to be turned on before they can be accessed. Failure to ensure that results in a seemingly random system crash (which would usually happen at boot with the interconnect driver built-in), resulting in the platform not booting up properly. Limit the number of bus_clocks to 2 (which is the maximum that SMD RPM interconnect supports anyway) and handle non-scaling clocks separately. Update MSM8996 and SDM660 drivers to make sure they do not regress with this change. This unfortunately has to be done in one patch to prevent either compile errors or broken bisect. Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> Link: https://lore.kernel.org/r/20230518195801.2556998-1-konrad.dybcio@linaro.org Signed-off-by: Georgi Djakov <djakov@kernel.org>
1 parent 32882f6 commit 2e2113c

4 files changed

Lines changed: 59 additions & 35 deletions

File tree

drivers/interconnect/qcom/icc-rpm.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ int qnoc_probe(struct platform_device *pdev)
409409
struct qcom_icc_provider *qp;
410410
struct icc_node *node;
411411
size_t num_nodes, i;
412-
const char * const *cds;
412+
const char * const *cds = NULL;
413413
int cd_num;
414414
int ret;
415415

@@ -424,28 +424,39 @@ int qnoc_probe(struct platform_device *pdev)
424424
qnodes = desc->nodes;
425425
num_nodes = desc->num_nodes;
426426

427-
if (desc->num_bus_clocks) {
428-
cds = desc->bus_clocks;
429-
cd_num = desc->num_bus_clocks;
427+
if (desc->num_intf_clocks) {
428+
cds = desc->intf_clocks;
429+
cd_num = desc->num_intf_clocks;
430430
} else {
431-
cds = bus_clocks;
432-
cd_num = ARRAY_SIZE(bus_clocks);
431+
/* 0 intf clocks is perfectly fine */
432+
cd_num = 0;
433433
}
434434

435-
qp = devm_kzalloc(dev, struct_size(qp, bus_clks, cd_num), GFP_KERNEL);
435+
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
436436
if (!qp)
437437
return -ENOMEM;
438438

439-
qp->bus_clk_rate = devm_kcalloc(dev, cd_num, sizeof(*qp->bus_clk_rate),
440-
GFP_KERNEL);
441-
if (!qp->bus_clk_rate)
439+
qp->intf_clks = devm_kzalloc(dev, sizeof(qp->intf_clks), GFP_KERNEL);
440+
if (!qp->intf_clks)
442441
return -ENOMEM;
443442

444443
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
445444
GFP_KERNEL);
446445
if (!data)
447446
return -ENOMEM;
448447

448+
qp->num_intf_clks = cd_num;
449+
for (i = 0; i < cd_num; i++)
450+
qp->intf_clks[i].id = cds[i];
451+
452+
if (desc->num_bus_clocks) {
453+
cds = desc->bus_clocks;
454+
cd_num = desc->num_bus_clocks;
455+
} else {
456+
cds = bus_clocks;
457+
cd_num = ARRAY_SIZE(bus_clocks);
458+
}
459+
449460
for (i = 0; i < cd_num; i++)
450461
qp->bus_clks[i].id = cds[i];
451462
qp->num_bus_clks = cd_num;
@@ -486,6 +497,10 @@ int qnoc_probe(struct platform_device *pdev)
486497
if (ret)
487498
return ret;
488499

500+
ret = devm_clk_bulk_get(dev, qp->num_intf_clks, qp->intf_clks);
501+
if (ret)
502+
return ret;
503+
489504
provider = &qp->provider;
490505
provider->dev = dev;
491506
provider->set = qcom_icc_set;
@@ -496,6 +511,11 @@ int qnoc_probe(struct platform_device *pdev)
496511

497512
icc_provider_init(provider);
498513

514+
/* If this fails, bus accesses will crash the platform! */
515+
ret = clk_bulk_prepare_enable(qp->num_intf_clks, qp->intf_clks);
516+
if (ret)
517+
return ret;
518+
499519
for (i = 0; i < num_nodes; i++) {
500520
size_t j;
501521

@@ -524,6 +544,8 @@ int qnoc_probe(struct platform_device *pdev)
524544
}
525545
data->num_nodes = num_nodes;
526546

547+
clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
548+
527549
ret = icc_provider_register(provider);
528550
if (ret)
529551
goto err_remove_nodes;

drivers/interconnect/qcom/icc-rpm.h

Lines changed: 12 additions & 2 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
2628
* @num_bus_clks: the total number of bus_clks clk_bulk_data entries
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;
3540
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
/**
@@ -93,6 +101,8 @@ struct qcom_icc_desc {
93101
size_t num_nodes;
94102
const char * const *bus_clocks;
95103
size_t num_bus_clocks;
104+
const char * const *intf_clocks;
105+
size_t num_intf_clocks;
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: 9 additions & 13 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,8 @@ 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-
.bus_clocks = bus_a0noc_clocks,
1825-
.num_bus_clocks = ARRAY_SIZE(bus_a0noc_clocks),
1820+
.intf_clocks = a0noc_intf_clocks,
1821+
.num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
18261822
.regmap_cfg = &msm8996_a0noc_regmap_config
18271823
};
18281824

@@ -1865,8 +1861,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
18651861
.type = QCOM_ICC_NOC,
18661862
.nodes = a2noc_nodes,
18671863
.num_nodes = ARRAY_SIZE(a2noc_nodes),
1868-
.bus_clocks = bus_a2noc_clocks,
1869-
.num_bus_clocks = ARRAY_SIZE(bus_a2noc_clocks),
1864+
.intf_clocks = a2noc_intf_clocks,
1865+
.num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
18701866
.regmap_cfg = &msm8996_a2noc_regmap_config
18711867
};
18721868

@@ -2004,8 +2000,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
20042000
.type = QCOM_ICC_NOC,
20052001
.nodes = mnoc_nodes,
20062002
.num_nodes = ARRAY_SIZE(mnoc_nodes),
2007-
.bus_clocks = bus_mm_clocks,
2008-
.num_bus_clocks = ARRAY_SIZE(bus_mm_clocks),
2003+
.intf_clocks = mm_intf_clocks,
2004+
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
20092005
.regmap_cfg = &msm8996_mnoc_regmap_config
20102006
};
20112007

drivers/interconnect/qcom/sdm660.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,11 @@ enum {
127127
SDM660_SNOC,
128128
};
129129

130-
static const char * const bus_mm_clocks[] = {
131-
"bus",
132-
"bus_a",
130+
static const char * const mm_intf_clocks[] = {
133131
"iface",
134132
};
135133

136-
static const char * const bus_a2noc_clocks[] = {
137-
"bus",
138-
"bus_a",
134+
static const char * const a2noc_intf_clocks[] = {
139135
"ipa",
140136
"ufs_axi",
141137
"aggre2_ufs_axi",
@@ -1516,8 +1512,8 @@ static const struct qcom_icc_desc sdm660_a2noc = {
15161512
.type = QCOM_ICC_NOC,
15171513
.nodes = sdm660_a2noc_nodes,
15181514
.num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes),
1519-
.bus_clocks = bus_a2noc_clocks,
1520-
.num_bus_clocks = ARRAY_SIZE(bus_a2noc_clocks),
1515+
.intf_clocks = a2noc_intf_clocks,
1516+
.num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
15211517
.regmap_cfg = &sdm660_a2noc_regmap_config,
15221518
};
15231519

@@ -1659,8 +1655,8 @@ static const struct qcom_icc_desc sdm660_mnoc = {
16591655
.type = QCOM_ICC_NOC,
16601656
.nodes = sdm660_mnoc_nodes,
16611657
.num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes),
1662-
.bus_clocks = bus_mm_clocks,
1663-
.num_bus_clocks = ARRAY_SIZE(bus_mm_clocks),
1658+
.intf_clocks = mm_intf_clocks,
1659+
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
16641660
.regmap_cfg = &sdm660_mnoc_regmap_config,
16651661
};
16661662

0 commit comments

Comments
 (0)