Skip to content

Commit 2db12b1

Browse files
ta72thierryreding
authored andcommitted
clk: tegra: Register clocks from root to leaf
Current clock initialization causes intermediate registering of orphan clocks (i.e. a clock without a parent registered). CCF keeps track of orphan clocks and any time a new clock is registered, it will loop through the list of orphan and queries if the parent is now available. This operation triggers one or more clock operations, which are IPCs with BPMP-FW. Hence, due to the order in which the clocks appear currently, this causes > 5000 IPC messages to be sent to BPMP-FW during clock initialization. Optimize the clock probing by registering clocks hierarchically from root clock towards leafs. Signed-off-by: Timo Alho <talho@nvidia.com> [jonathanh@nvidia.com: checkpatch fixes] Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
1 parent 23a43cc commit 2db12b1

1 file changed

Lines changed: 56 additions & 16 deletions

File tree

drivers/clk/tegra/clk-bpmp.c

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -448,15 +448,29 @@ static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp,
448448
return count;
449449
}
450450

451+
static unsigned int
452+
tegra_bpmp_clk_id_to_index(const struct tegra_bpmp_clk_info *clocks,
453+
unsigned int num_clocks, unsigned int id)
454+
{
455+
unsigned int i;
456+
457+
for (i = 0; i < num_clocks; i++)
458+
if (clocks[i].id == id)
459+
return i;
460+
461+
return UINT_MAX;
462+
}
463+
451464
static const struct tegra_bpmp_clk_info *
452465
tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks,
453466
unsigned int num_clocks, unsigned int id)
454467
{
455468
unsigned int i;
456469

457-
for (i = 0; i < num_clocks; i++)
458-
if (clocks[i].id == id)
459-
return &clocks[i];
470+
i = tegra_bpmp_clk_id_to_index(clocks, num_clocks, id);
471+
472+
if (i < num_clocks)
473+
return &clocks[i];
460474

461475
return NULL;
462476
}
@@ -539,31 +553,57 @@ tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
539553
return clk;
540554
}
541555

556+
static void tegra_bpmp_register_clocks_one(struct tegra_bpmp *bpmp,
557+
struct tegra_bpmp_clk_info *infos,
558+
unsigned int i,
559+
unsigned int count)
560+
{
561+
unsigned int j;
562+
struct tegra_bpmp_clk_info *info;
563+
struct tegra_bpmp_clk *clk;
564+
565+
if (bpmp->clocks[i]) {
566+
/* already registered */
567+
return;
568+
}
569+
570+
info = &infos[i];
571+
for (j = 0; j < info->num_parents; ++j) {
572+
unsigned int p_id = info->parents[j];
573+
unsigned int p_i = tegra_bpmp_clk_id_to_index(infos, count,
574+
p_id);
575+
if (p_i < count)
576+
tegra_bpmp_register_clocks_one(bpmp, infos, p_i, count);
577+
}
578+
579+
clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
580+
if (IS_ERR(clk)) {
581+
dev_err(bpmp->dev,
582+
"failed to register clock %u (%s): %ld\n",
583+
info->id, info->name, PTR_ERR(clk));
584+
/* intentionally store the error pointer to
585+
* bpmp->clocks[i] to avoid re-attempting the
586+
* registration later
587+
*/
588+
}
589+
590+
bpmp->clocks[i] = clk;
591+
}
592+
542593
static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp,
543594
struct tegra_bpmp_clk_info *infos,
544595
unsigned int count)
545596
{
546-
struct tegra_bpmp_clk *clk;
547597
unsigned int i;
548598

549599
bpmp->num_clocks = count;
550600

551-
bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL);
601+
bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(struct tegra_bpmp_clk), GFP_KERNEL);
552602
if (!bpmp->clocks)
553603
return -ENOMEM;
554604

555605
for (i = 0; i < count; i++) {
556-
struct tegra_bpmp_clk_info *info = &infos[i];
557-
558-
clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
559-
if (IS_ERR(clk)) {
560-
dev_err(bpmp->dev,
561-
"failed to register clock %u (%s): %ld\n",
562-
info->id, info->name, PTR_ERR(clk));
563-
continue;
564-
}
565-
566-
bpmp->clocks[i] = clk;
606+
tegra_bpmp_register_clocks_one(bpmp, infos, i, count);
567607
}
568608

569609
return 0;

0 commit comments

Comments
 (0)