clk: tegra: Support BPMP-FW ABI deny flags
authorPeter De Schrijver <pdeschrijver@nvidia.com>
Thu, 27 Oct 2022 12:13:55 +0000 (15:13 +0300)
committerThierry Reding <treding@nvidia.com>
Sat, 19 Nov 2022 01:00:32 +0000 (02:00 +0100)
Support BPMP_CLK_STATE_CHANGE_DENIED by not populating state changing
operations when the flag is set.

Support BPMP_CLK_RATE_PARENT_CHANGE_DENIED by not populating rate or
parent changing operations when the flag is set.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/clk/tegra/clk-bpmp.c

index d82a71f10c2c182309653e4c1ea7230e79396af8..0ecdffaa6b16a6d3ca2f7bc8731968c804fcbc09 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (C) 2016-2020 NVIDIA Corporation
+ * Copyright (C) 2016-2022 NVIDIA Corporation
  */
 
 #include <linux/clk-provider.h>
@@ -310,6 +310,23 @@ static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = {
        .set_rate = tegra_bpmp_clk_set_rate,
 };
 
+static const struct clk_ops tegra_bpmp_clk_mux_read_only_ops = {
+       .get_parent = tegra_bpmp_clk_get_parent,
+       .recalc_rate = tegra_bpmp_clk_recalc_rate,
+};
+
+static const struct clk_ops tegra_bpmp_clk_read_only_ops = {
+       .recalc_rate = tegra_bpmp_clk_recalc_rate,
+};
+
+static const struct clk_ops tegra_bpmp_clk_gate_mux_read_only_ops = {
+       .prepare = tegra_bpmp_clk_prepare,
+       .unprepare = tegra_bpmp_clk_unprepare,
+       .is_prepared = tegra_bpmp_clk_is_prepared,
+       .recalc_rate = tegra_bpmp_clk_recalc_rate,
+       .get_parent = tegra_bpmp_clk_get_parent,
+};
+
 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp)
 {
        struct cmd_clk_get_max_clk_id_response response;
@@ -510,8 +527,22 @@ tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
        memset(&init, 0, sizeof(init));
        init.name = info->name;
        clk->hw.init = &init;
-
-       if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
+       if (info->flags & BPMP_CLK_STATE_CHANGE_DENIED) {
+               if ((info->flags & BPMP_CLK_RATE_PARENT_CHANGE_DENIED) == 0) {
+                       dev_WARN(bpmp->dev,
+                               "Firmware bug! Inconsistent permission bits for clock %s. State and parent/rate changes disabled.",
+                                init.name);
+               }
+               if (info->flags & TEGRA_BPMP_CLK_HAS_MUX)
+                       init.ops = &tegra_bpmp_clk_mux_read_only_ops;
+               else
+                       init.ops = &tegra_bpmp_clk_read_only_ops;
+       } else if (info->flags & BPMP_CLK_RATE_PARENT_CHANGE_DENIED) {
+               if (info->flags & TEGRA_BPMP_CLK_HAS_MUX)
+                       init.ops = &tegra_bpmp_clk_gate_mux_read_only_ops;
+               else
+                       init.ops = &tegra_bpmp_clk_gate_ops;
+       } else if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
                if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
                        init.ops = &tegra_bpmp_clk_mux_rate_ops;
                else