Skip to content

Commit 5fed7fe

Browse files
author
Georgi Djakov
committed
Merge branch 'icc-sa8775p' into icc-next
Add Epoch Subsystem (EPSS) L3 provider support on SA8775P SoCs. Current interconnect framework is based on static IDs for creating node and registering with framework. This becomes a limitation for topologies where there are multiple instances of same interconnect provider. Modified interconnect framework APIs to create and link icc node with dynamic IDs, this will help to overcome the dependency on static IDs. * icc-sa8775p dt-bindings: interconnect: Add EPSS L3 compatible for SA8775P interconnect: core: Add dynamic id allocation support interconnect: qcom: Add multidev EPSS L3 support interconnect: qcom: icc-rpmh: Add dynamic icc node id support interconnect: qcom: sa8775p: Add dynamic icc node id support Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Georgi Djakov <[email protected]>
2 parents b0779ea + b124464 commit 5fed7fe

File tree

8 files changed

+475
-635
lines changed

8 files changed

+475
-635
lines changed

Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ properties:
2828
- const: qcom,osm-l3
2929
- items:
3030
- enum:
31+
- qcom,sa8775p-epss-l3
3132
- qcom,sc7280-epss-l3
3233
- qcom,sc8280xp-epss-l3
3334
- qcom,sm6375-cpucp-l3

drivers/interconnect/core.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "internal.h"
2222

23+
#define ICC_DYN_ID_START 10000
24+
2325
#define CREATE_TRACE_POINTS
2426
#include "trace.h"
2527

@@ -826,7 +828,12 @@ static struct icc_node *icc_node_create_nolock(int id)
826828
if (!node)
827829
return ERR_PTR(-ENOMEM);
828830

829-
id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL);
831+
/* dynamic id allocation */
832+
if (id == ICC_ALLOC_DYN_ID)
833+
id = idr_alloc(&icc_idr, node, ICC_DYN_ID_START, 0, GFP_KERNEL);
834+
else
835+
id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL);
836+
830837
if (id < 0) {
831838
WARN(1, "%s: couldn't get idr\n", __func__);
832839
kfree(node);
@@ -838,6 +845,25 @@ static struct icc_node *icc_node_create_nolock(int id)
838845
return node;
839846
}
840847

848+
/**
849+
* icc_node_create_dyn() - create a node with dynamic id
850+
*
851+
* Return: icc_node pointer on success, or ERR_PTR() on error
852+
*/
853+
struct icc_node *icc_node_create_dyn(void)
854+
{
855+
struct icc_node *node;
856+
857+
mutex_lock(&icc_lock);
858+
859+
node = icc_node_create_nolock(ICC_ALLOC_DYN_ID);
860+
861+
mutex_unlock(&icc_lock);
862+
863+
return node;
864+
}
865+
EXPORT_SYMBOL_GPL(icc_node_create_dyn);
866+
841867
/**
842868
* icc_node_create() - create a node
843869
* @id: node id
@@ -884,6 +910,56 @@ void icc_node_destroy(int id)
884910
}
885911
EXPORT_SYMBOL_GPL(icc_node_destroy);
886912

913+
/**
914+
* icc_link_nodes() - create link between two nodes
915+
* @src_node: source node
916+
* @dst_node: destination node
917+
*
918+
* Create a link between two nodes. The nodes might belong to different
919+
* interconnect providers and the @dst_node might not exist (if the
920+
* provider driver has not probed yet). So just create the @dst_node
921+
* and when the actual provider driver is probed, the rest of the node
922+
* data is filled.
923+
*
924+
* Return: 0 on success, or an error code otherwise
925+
*/
926+
int icc_link_nodes(struct icc_node *src_node, struct icc_node **dst_node)
927+
{
928+
struct icc_node **new;
929+
int ret = 0;
930+
931+
if (!src_node->provider)
932+
return -EINVAL;
933+
934+
mutex_lock(&icc_lock);
935+
936+
if (!*dst_node) {
937+
*dst_node = icc_node_create_nolock(ICC_ALLOC_DYN_ID);
938+
939+
if (IS_ERR(*dst_node)) {
940+
ret = PTR_ERR(*dst_node);
941+
goto out;
942+
}
943+
}
944+
945+
new = krealloc(src_node->links,
946+
(src_node->num_links + 1) * sizeof(*src_node->links),
947+
GFP_KERNEL);
948+
if (!new) {
949+
ret = -ENOMEM;
950+
goto out;
951+
}
952+
953+
src_node->links = new;
954+
src_node->links[src_node->num_links++] = *dst_node;
955+
956+
out:
957+
mutex_unlock(&icc_lock);
958+
959+
return ret;
960+
}
961+
EXPORT_SYMBOL_GPL(icc_link_nodes);
962+
887963
/**
888964
* icc_link_create() - create a link between two nodes
889965
* @node: source node id
@@ -962,6 +1038,10 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
9621038
node->avg_bw = node->init_avg;
9631039
node->peak_bw = node->init_peak;
9641040

1041+
if (node->id >= ICC_DYN_ID_START)
1042+
node->name = devm_kasprintf(provider->dev, GFP_KERNEL, "%s@%s",
1043+
node->name, dev_name(provider->dev));
1044+
9651045
if (node->avg_bw || node->peak_bw) {
9661046
if (provider->pre_aggregate)
9671047
provider->pre_aggregate(node);

drivers/interconnect/qcom/icc-rpmh.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,14 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
280280
if (!qn)
281281
continue;
282282

283-
node = icc_node_create(qn->id);
283+
if (desc->alloc_dyn_id) {
284+
if (!qn->node)
285+
qn->node = icc_node_create_dyn();
286+
node = qn->node;
287+
} else {
288+
node = icc_node_create(qn->id);
289+
}
290+
284291
if (IS_ERR(node)) {
285292
ret = PTR_ERR(node);
286293
goto err_remove_nodes;
@@ -290,8 +297,12 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
290297
node->data = qn;
291298
icc_node_add(node, provider);
292299

293-
for (j = 0; j < qn->num_links; j++)
294-
icc_link_create(node, qn->links[j]);
300+
for (j = 0; j < qn->num_links; j++) {
301+
if (desc->alloc_dyn_id)
302+
icc_link_nodes(node, &qn->link_nodes[j]->node);
303+
else
304+
icc_link_create(node, qn->links[j]);
305+
}
295306

296307
data->nodes[i] = node;
297308
}

drivers/interconnect/qcom/icc-rpmh.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ struct qcom_icc_qosbox {
8383
* @name: the node name used in debugfs
8484
* @links: an array of nodes where we can go next while traversing
8585
* @id: a unique node identifier
86+
* @link_nodes: links associated with this node
87+
* @node: icc_node associated with this node
8688
* @num_links: the total number of @links
8789
* @channels: num of channels at this node
8890
* @buswidth: width of the interconnect between a node and the bus
@@ -96,6 +98,8 @@ struct qcom_icc_node {
9698
const char *name;
9799
u16 links[MAX_LINKS];
98100
u16 id;
101+
struct qcom_icc_node **link_nodes;
102+
struct icc_node *node;
99103
u16 num_links;
100104
u16 channels;
101105
u16 buswidth;
@@ -154,6 +158,7 @@ struct qcom_icc_desc {
154158
struct qcom_icc_bcm * const *bcms;
155159
size_t num_bcms;
156160
bool qos_requires_clocks;
161+
bool alloc_dyn_id;
157162
};
158163

159164
int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,

drivers/interconnect/qcom/osm-l3.c

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/*
33
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
4+
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
45
*/
56

67
#include <linux/args.h>
@@ -32,8 +33,6 @@
3233
#define EPSS_REG_FREQ_LUT 0x100
3334
#define EPSS_REG_PERF_STATE 0x320
3435

35-
#define OSM_L3_MAX_LINKS 1
36-
3736
#define to_osm_l3_provider(_provider) \
3837
container_of(_provider, struct qcom_osm_l3_icc_provider, provider)
3938

@@ -48,16 +47,10 @@ struct qcom_osm_l3_icc_provider {
4847
/**
4948
* struct qcom_osm_l3_node - Qualcomm specific interconnect nodes
5049
* @name: the node name used in debugfs
51-
* @links: an array of nodes where we can go next while traversing
52-
* @id: a unique node identifier
53-
* @num_links: the total number of @links
5450
* @buswidth: width of the interconnect between a node and the bus
5551
*/
5652
struct qcom_osm_l3_node {
5753
const char *name;
58-
u16 links[OSM_L3_MAX_LINKS];
59-
u16 id;
60-
u16 num_links;
6154
u16 buswidth;
6255
};
6356

@@ -69,30 +62,22 @@ struct qcom_osm_l3_desc {
6962
unsigned int reg_perf_state;
7063
};
7164

72-
enum {
73-
OSM_L3_MASTER_NODE = 10000,
74-
OSM_L3_SLAVE_NODE,
75-
};
76-
77-
#define DEFINE_QNODE(_name, _id, _buswidth, ...) \
65+
#define DEFINE_QNODE(_name, _buswidth) \
7866
static const struct qcom_osm_l3_node _name = { \
7967
.name = #_name, \
80-
.id = _id, \
8168
.buswidth = _buswidth, \
82-
.num_links = COUNT_ARGS(__VA_ARGS__), \
83-
.links = { __VA_ARGS__ }, \
8469
}
8570

86-
DEFINE_QNODE(osm_l3_master, OSM_L3_MASTER_NODE, 16, OSM_L3_SLAVE_NODE);
87-
DEFINE_QNODE(osm_l3_slave, OSM_L3_SLAVE_NODE, 16);
71+
DEFINE_QNODE(osm_l3_slave, 16);
72+
DEFINE_QNODE(osm_l3_master, 16);
8873

8974
static const struct qcom_osm_l3_node * const osm_l3_nodes[] = {
9075
[MASTER_OSM_L3_APPS] = &osm_l3_master,
9176
[SLAVE_OSM_L3] = &osm_l3_slave,
9277
};
9378

94-
DEFINE_QNODE(epss_l3_master, OSM_L3_MASTER_NODE, 32, OSM_L3_SLAVE_NODE);
95-
DEFINE_QNODE(epss_l3_slave, OSM_L3_SLAVE_NODE, 32);
79+
DEFINE_QNODE(epss_l3_slave, 32);
80+
DEFINE_QNODE(epss_l3_master, 32);
9681

9782
static const struct qcom_osm_l3_node * const epss_l3_nodes[] = {
9883
[MASTER_EPSS_L3_APPS] = &epss_l3_master,
@@ -242,10 +227,10 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
242227

243228
icc_provider_init(provider);
244229

230+
/* Create nodes */
245231
for (i = 0; i < num_nodes; i++) {
246-
size_t j;
232+
node = icc_node_create_dyn();
247233

248-
node = icc_node_create(qnodes[i]->id);
249234
if (IS_ERR(node)) {
250235
ret = PTR_ERR(node);
251236
goto err;
@@ -256,12 +241,12 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
256241
node->data = (void *)qnodes[i];
257242
icc_node_add(node, provider);
258243

259-
for (j = 0; j < qnodes[i]->num_links; j++)
260-
icc_link_create(node, qnodes[i]->links[j]);
261-
262244
data->nodes[i] = node;
263245
}
264246

247+
/* Create link */
248+
icc_link_nodes(data->nodes[MASTER_OSM_L3_APPS], &data->nodes[SLAVE_OSM_L3]);
249+
265250
ret = icc_provider_register(provider);
266251
if (ret)
267252
goto err;
@@ -278,6 +263,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
278263
static const struct of_device_id osm_l3_of_match[] = {
279264
{ .compatible = "qcom,epss-l3", .data = &epss_l3_l3_vote },
280265
{ .compatible = "qcom,osm-l3", .data = &osm_l3 },
266+
{ .compatible = "qcom,sa8775p-epss-l3", .data = &epss_l3_perf_state },
281267
{ .compatible = "qcom,sc7180-osm-l3", .data = &osm_l3 },
282268
{ .compatible = "qcom,sc7280-epss-l3", .data = &epss_l3_perf_state },
283269
{ .compatible = "qcom,sdm845-osm-l3", .data = &osm_l3 },

0 commit comments

Comments
 (0)