2023-06-14 18:28:49

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 00/22] Restructure RPM SMD ICC

This series reshuffles things around, moving the management of SMD RPM
bus clocks to the interconnect framework where they belong. This helps
us solve a couple of issues:

1. We can work towards unused clk cleanup of RPMCC without worrying
about it killing some NoC bus, resulting in the SoC dying.
Deasserting actually unused RPM clocks (among other things) will
let us achieve "true SoC-wide power collapse states", also known as
VDD_LOW and VDD_MIN.

2. We no longer have to keep tons of quirky bus clock ifs in the icc
driver. You either have a RPM clock and call "rpm set rate" or you
have a single non-RPM clock (like AHB_CLK_SRC) or you don't have any.

3. There's less overhead - instead of going through layers and layers of
the CCF, ratesetting comes down to calling max() and sending a single
RPM message. ICC is very very dynamic so that's a big plus.

The clocks still need to be vaguely described in the clk-smd-rpm driver,
as it gives them an initial kickoff, before actually telling RPM to
enable DVFS scaling. After RPM receives that command, all clocks that
have not been assigned a rate are considered unused and are shut down
in hardware, leading to the same issue as described in point 1.

We can consider marking them __initconst in the future, but this series
is very fat even without that..

Apart from that, it squashes a couple of bugs that really need fixing..

--- MERGING STRATEGY ---
If Stephen and Georgi agree, it would be best to take all of this through
the qcom tree, as it touches on heavily intertwined components and
introduces compile-time dependencies between icc and clk drivers.

Tested on SM6375 (OOT), MSM8998 (OOT), MSM8996.

MSM8974 conversion to common code and modernization will be handled separately.

Signed-off-by: Konrad Dybcio <[email protected]>
---
Changes in v6:
- Fix argument naming in "Add rpmcc handling skeleton code"
- Fix missing clk.h and reorder patch "Add missing headers in icc-rpm.h",
drop Dmitry's rb
- Pick up tags
- Link to v5: https://lore.kernel.org/r/[email protected]

Changes in v5:
- Pass RPM context id to qcom_icc_rpm_set_bus_rate()
- Fix min_t call cutting off bits 32-63 in set() path
- Pick up tags
- Link to v4: https://lore.kernel.org/r/[email protected]

Changes in v4:
- Only set clk rate on a context if necessary
- Mention qcom,icc.h is not the correct header in "Control bus rpmcc form icc"
- Fix the bindings (BIT vs 1<<)
- Fix one more wrong use of qcom,icc.h in "Fix bucket numer" and uninclude it
- Drop "Allow negative QoS offset" (will be handled separately)
- Export icc clocks descriptions to unbreak =m builds
- Pick up tags
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- Use devm_clk_get_optional and only get() the clock once
- Drop unnecessary NULL-checks for qp->bus_clk
- Handle ARM32 CCF limitations, add an explicit comment about them
- Use Stephan's alternative rpmcc readiness check
- Fix one more wrong usage of QCOM_ICC_NUM_BUCKETS in icc-rpm.h
- Introduce new dt-bindings for icc rpm tags
- Mention the rpm tags situation in the commit message of
"Fix bucket number"
- Pick up tags
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Sort entries properly in "Add missing headers in icc-rpm.h"
- Fix the check for no clocks on a given provider
- Replace "Divide clk rate by src node bus width" with a proper fix
- Add "Set correct bandwidth through RPM bw req"
- Split "Add QCOM_SMD_RPM_STATE_NUM" into 2 logical changes
- Move "Separate out interconnect bus clocks" a bit later in the series
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Konrad Dybcio (21):
dt-bindings: interconnect: Add Qcom RPM ICC bindings
soc: qcom: smd-rpm: Add QCOM_SMD_RPM_STATE_NUM
soc: qcom: smd-rpm: Use tabs for defines
clk: qcom: smd-rpm: Move some RPM resources to the common header
interconnect: qcom: icc-rpm: Introduce keep_alive
interconnect: qcom: Add missing headers in icc-rpm.h
interconnect: qcom: Fold smd-rpm.h into icc-rpm.h
interconnect: qcom: smd-rpm: Add rpmcc handling skeleton code
interconnect: qcom: Define RPM bus clocks
interconnect: qcom: sdm660: Hook up RPM bus clk definitions
interconnect: qcom: msm8996: Hook up RPM bus clk definitions
interconnect: qcom: qcs404: Hook up RPM bus clk definitions
interconnect: qcom: msm8939: Hook up RPM bus clk definitions
interconnect: qcom: msm8916: Hook up RPM bus clk definitions
interconnect: qcom: qcm2290: Hook up RPM bus clk definitions
interconnect: qcom: icc-rpm: Control bus rpmcc from icc
clk: qcom: smd-rpm: Separate out interconnect bus clocks
interconnect: qcom: icc-rpm: Fix bucket number
interconnect: qcom: icc-rpm: Set bandwidth on both contexts
interconnect: qcom: icc-rpm: Set correct bandwidth through RPM bw req
interconnect: qcom: icc-rpm: Fix bandwidth calculations

Stephan Gerhold (1):
soc: qcom: smd-rpm: Move icc_smd_rpm registration to clk-smd-rpm

drivers/clk/qcom/clk-smd-rpm.c | 312 +++++++++++-------------
drivers/interconnect/qcom/Makefile | 2 +-
drivers/interconnect/qcom/icc-rpm-clocks.c | 77 ++++++
drivers/interconnect/qcom/icc-rpm.c | 220 +++++++++--------
drivers/interconnect/qcom/icc-rpm.h | 56 ++++-
drivers/interconnect/qcom/msm8916.c | 5 +-
drivers/interconnect/qcom/msm8939.c | 6 +-
drivers/interconnect/qcom/msm8974.c | 2 +-
drivers/interconnect/qcom/msm8996.c | 10 +-
drivers/interconnect/qcom/qcm2290.c | 8 +-
drivers/interconnect/qcom/qcs404.c | 5 +-
drivers/interconnect/qcom/sdm660.c | 8 +-
drivers/interconnect/qcom/smd-rpm.c | 23 +-
drivers/interconnect/qcom/smd-rpm.h | 15 --
drivers/soc/qcom/smd-rpm.c | 17 +-
include/dt-bindings/interconnect/qcom,rpm-icc.h | 13 +
include/linux/soc/qcom/smd-rpm.h | 20 +-
17 files changed, 455 insertions(+), 344 deletions(-)
---
base-commit: b16049b21162bb649cdd8519642a35972b7910fe
change-id: 20230526-topic-smd_icc-b8213948a5ed

Best regards,
--
Konrad Dybcio <[email protected]>



2023-06-14 18:31:58

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 15/22] interconnect: qcom: msm8916: Hook up RPM bus clk definitions

Assign the necessary definitions to migrate to the new bus clock
handling mechanism.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Reviewed-by: Stephan Gerhold <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/msm8916.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c
index 70b67fbe453f..b567a2b4199c 100644
--- a/drivers/interconnect/qcom/msm8916.c
+++ b/drivers/interconnect/qcom/msm8916.c
@@ -1230,6 +1230,7 @@ static const struct qcom_icc_desc msm8916_snoc = {
.type = QCOM_ICC_NOC,
.nodes = msm8916_snoc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_snoc_nodes),
+ .bus_clk_desc = &bus_1_clk,
.regmap_cfg = &msm8916_snoc_regmap_config,
.qos_offset = 0x7000,
};
@@ -1258,6 +1259,7 @@ static const struct qcom_icc_desc msm8916_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = msm8916_bimc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_bimc_nodes),
+ .bus_clk_desc = &bimc_clk,
.regmap_cfg = &msm8916_bimc_regmap_config,
.qos_offset = 0x8000,
};
@@ -1327,6 +1329,7 @@ static const struct qcom_icc_desc msm8916_pcnoc = {
.type = QCOM_ICC_NOC,
.nodes = msm8916_pcnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_pcnoc_nodes),
+ .bus_clk_desc = &bus_0_clk,
.regmap_cfg = &msm8916_pcnoc_regmap_config,
.qos_offset = 0x7000,
};

--
2.41.0


2023-06-14 18:38:58

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 04/22] clk: qcom: smd-rpm: Move some RPM resources to the common header

In preparation for handling the bus clocks in the icc driver, carve out
some defines and a struct definition to the common rpm header.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/clk/qcom/clk-smd-rpm.c | 13 -------------
include/linux/soc/qcom/smd-rpm.h | 15 +++++++++++++++
2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index e4de74b68797..937cb1515968 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -18,13 +18,6 @@

#include <dt-bindings/clock/qcom,rpmcc.h>

-#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
-#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
-#define QCOM_RPM_SMD_KEY_RATE 0x007a484b
-#define QCOM_RPM_SMD_KEY_ENABLE 0x62616e45
-#define QCOM_RPM_SMD_KEY_STATE 0x54415453
-#define QCOM_RPM_SCALING_ENABLE_ID 0x2
-
#define __DEFINE_CLK_SMD_RPM_PREFIX(_prefix, _name, _active, \
type, r_id, key) \
static struct clk_smd_rpm clk_smd_rpm_##_prefix##_active; \
@@ -171,12 +164,6 @@ struct clk_smd_rpm {
unsigned long rate;
};

-struct clk_smd_rpm_req {
- __le32 key;
- __le32 nbytes;
- __le32 value;
-};
-
struct rpm_smd_clk_desc {
struct clk_smd_rpm **clks;
size_t num_clks;
diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h
index 99499e4b080e..8190878645f9 100644
--- a/include/linux/soc/qcom/smd-rpm.h
+++ b/include/linux/soc/qcom/smd-rpm.h
@@ -2,6 +2,8 @@
#ifndef __QCOM_SMD_RPM_H__
#define __QCOM_SMD_RPM_H__

+#include <linux/types.h>
+
struct qcom_smd_rpm;

#define QCOM_SMD_RPM_ACTIVE_STATE 0
@@ -45,6 +47,19 @@ struct qcom_smd_rpm;
#define QCOM_SMD_RPM_PKA_CLK 0x616b70
#define QCOM_SMD_RPM_MCFG_CLK 0x6766636d

+#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
+#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
+#define QCOM_RPM_SMD_KEY_RATE 0x007a484b
+#define QCOM_RPM_SMD_KEY_ENABLE 0x62616e45
+#define QCOM_RPM_SMD_KEY_STATE 0x54415453
+#define QCOM_RPM_SCALING_ENABLE_ID 0x2
+
+struct clk_smd_rpm_req {
+ __le32 key;
+ __le32 nbytes;
+ __le32 value;
+};
+
int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
int state,
u32 resource_type, u32 resource_id,

--
2.41.0


2023-06-14 18:39:22

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 01/22] dt-bindings: interconnect: Add Qcom RPM ICC bindings

The SMD RPM interconnect driver requires different icc tags to the
RPMh driver. Add bindings to reflect that.

Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
include/dt-bindings/interconnect/qcom,rpm-icc.h | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/include/dt-bindings/interconnect/qcom,rpm-icc.h b/include/dt-bindings/interconnect/qcom,rpm-icc.h
new file mode 100644
index 000000000000..2cd56f91e5c5
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,rpm-icc.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_RPM_ICC_H
+#define __DT_BINDINGS_INTERCONNECT_QCOM_RPM_ICC_H
+
+#define RPM_ACTIVE_TAG (1 << 0)
+#define RPM_SLEEP_TAG (1 << 1)
+#define RPM_ALWAYS_TAG (RPM_ACTIVE_TAG | RPM_SLEEP_TAG)
+
+#endif

--
2.41.0


2023-06-14 18:40:03

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 10/22] interconnect: qcom: Define RPM bus clocks

Add the definitions for RPM bus clocks that will be used by many
different platforms.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/Makefile | 2 +-
drivers/interconnect/qcom/icc-rpm-clocks.c | 77 ++++++++++++++++++++++++++++++
drivers/interconnect/qcom/icc-rpm.h | 13 +++++
3 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index ab988926433c..80d9d2da95d1 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -29,7 +29,7 @@ qnoc-sm8250-objs := sm8250.o
qnoc-sm8350-objs := sm8350.o
qnoc-sm8450-objs := sm8450.o
qnoc-sm8550-objs := sm8550.o
-icc-smd-rpm-objs := smd-rpm.o icc-rpm.o
+icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o

obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
diff --git a/drivers/interconnect/qcom/icc-rpm-clocks.c b/drivers/interconnect/qcom/icc-rpm-clocks.c
new file mode 100644
index 000000000000..63c82a91bbc7
--- /dev/null
+++ b/drivers/interconnect/qcom/icc-rpm-clocks.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Linaro Ltd
+ */
+
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include "icc-rpm.h"
+
+const struct rpm_clk_resource aggre1_clk = {
+ .resource_type = QCOM_SMD_RPM_AGGR_CLK,
+ .clock_id = 1,
+};
+EXPORT_SYMBOL_GPL(aggre1_clk);
+
+const struct rpm_clk_resource aggre2_clk = {
+ .resource_type = QCOM_SMD_RPM_AGGR_CLK,
+ .clock_id = 2,
+};
+EXPORT_SYMBOL_GPL(aggre2_clk);
+
+const struct rpm_clk_resource bimc_clk = {
+ .resource_type = QCOM_SMD_RPM_MEM_CLK,
+ .clock_id = 0,
+};
+EXPORT_SYMBOL_GPL(bimc_clk);
+
+const struct rpm_clk_resource bus_0_clk = {
+ .resource_type = QCOM_SMD_RPM_BUS_CLK,
+ .clock_id = 0,
+};
+EXPORT_SYMBOL_GPL(bus_0_clk);
+
+const struct rpm_clk_resource bus_1_clk = {
+ .resource_type = QCOM_SMD_RPM_BUS_CLK,
+ .clock_id = 1,
+};
+EXPORT_SYMBOL_GPL(bus_1_clk);
+
+const struct rpm_clk_resource bus_2_clk = {
+ .resource_type = QCOM_SMD_RPM_BUS_CLK,
+ .clock_id = 2,
+};
+EXPORT_SYMBOL_GPL(bus_2_clk);
+
+const struct rpm_clk_resource mmaxi_0_clk = {
+ .resource_type = QCOM_SMD_RPM_MMAXI_CLK,
+ .clock_id = 0,
+};
+EXPORT_SYMBOL_GPL(mmaxi_0_clk);
+
+const struct rpm_clk_resource mmaxi_1_clk = {
+ .resource_type = QCOM_SMD_RPM_MMAXI_CLK,
+ .clock_id = 1,
+};
+EXPORT_SYMBOL_GPL(mmaxi_1_clk);
+
+const struct rpm_clk_resource qup_clk = {
+ .resource_type = QCOM_SMD_RPM_QUP_CLK,
+ .clock_id = 0,
+};
+EXPORT_SYMBOL_GPL(qup_clk);
+
+/* Branch clocks */
+const struct rpm_clk_resource aggre1_branch_clk = {
+ .resource_type = QCOM_SMD_RPM_AGGR_CLK,
+ .clock_id = 1,
+ .branch = true,
+};
+EXPORT_SYMBOL_GPL(aggre1_branch_clk);
+
+const struct rpm_clk_resource aggre2_branch_clk = {
+ .resource_type = QCOM_SMD_RPM_AGGR_CLK,
+ .clock_id = 2,
+ .branch = true,
+};
+EXPORT_SYMBOL_GPL(aggre2_branch_clk);
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 5c43a8023ffa..ecd6104335a7 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -137,6 +137,19 @@ enum qos_mode {
NOC_QOS_MODE_BYPASS,
};

+extern const struct rpm_clk_resource aggre1_clk;
+extern const struct rpm_clk_resource aggre2_clk;
+extern const struct rpm_clk_resource bimc_clk;
+extern const struct rpm_clk_resource bus_0_clk;
+extern const struct rpm_clk_resource bus_1_clk;
+extern const struct rpm_clk_resource bus_2_clk;
+extern const struct rpm_clk_resource mmaxi_0_clk;
+extern const struct rpm_clk_resource mmaxi_1_clk;
+extern const struct rpm_clk_resource qup_clk;
+
+extern const struct rpm_clk_resource aggre1_branch_clk;
+extern const struct rpm_clk_resource aggre2_branch_clk;
+
int qnoc_probe(struct platform_device *pdev);
int qnoc_remove(struct platform_device *pdev);


--
2.41.0


2023-06-14 18:41:33

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 09/22] interconnect: qcom: smd-rpm: Add rpmcc handling skeleton code

Introduce qcom_icc_rpm_set_bus_rate() in preparation for handling RPM
clock resources within the interconnect framework. This lets us greatly
simplify all of the code handling, as setting the rate comes down to:

u32 rate_khz = max(clk.sleep_rate, clk.active_rate, clk_a.active_rate)
write_to_rpm(clock.description, rate_khz);

Reviewed-by: Stephan Gerhold <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.h | 15 +++++++++++++++
drivers/interconnect/qcom/smd-rpm.c | 21 +++++++++++++++++++++
2 files changed, 36 insertions(+)

diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 4755e422d2d1..5c43a8023ffa 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -25,6 +25,18 @@ enum qcom_icc_type {
QCOM_ICC_QNOC,
};

+/**
+ * struct rpm_clk_resource - RPM bus clock resource
+ * @resource_type: RPM resource type of the clock resource
+ * @clock_id: index of the clock resource of a specific resource type
+ * @branch: whether the resource represents a branch clock
+*/
+struct rpm_clk_resource {
+ u32 resource_type;
+ u32 clock_id;
+ bool branch;
+};
+
#define NUM_BUS_CLKS 2

/**
@@ -50,6 +62,7 @@ struct qcom_icc_provider {
unsigned int qos_offset;
u64 bus_clk_rate[NUM_BUS_CLKS];
struct clk_bulk_data bus_clks[NUM_BUS_CLKS];
+ const struct rpm_clk_resource *bus_clk_desc;
struct clk_bulk_data *intf_clks;
bool keep_alive;
bool is_on;
@@ -107,6 +120,7 @@ struct qcom_icc_desc {
struct qcom_icc_node * const *nodes;
size_t num_nodes;
const char * const *bus_clocks;
+ const struct rpm_clk_resource *bus_clk_desc;
const char * const *intf_clocks;
size_t num_intf_clocks;
bool keep_alive;
@@ -128,5 +142,6 @@ int qnoc_remove(struct platform_device *pdev);

bool qcom_icc_rpm_smd_available(void);
int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val);
+int qcom_icc_rpm_set_bus_rate(const struct rpm_clk_resource *clk, int ctx, u32 rate);

#endif
diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c
index b0183262ba66..24bc994e1a12 100644
--- a/drivers/interconnect/qcom/smd-rpm.c
+++ b/drivers/interconnect/qcom/smd-rpm.c
@@ -16,6 +16,7 @@
#include "icc-rpm.h"

#define RPM_KEY_BW 0x00007762
+#define QCOM_RPM_SMD_KEY_RATE 0x007a484b

static struct qcom_smd_rpm *icc_smd_rpm;

@@ -44,6 +45,26 @@ int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val)
}
EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_send);

+int qcom_icc_rpm_set_bus_rate(const struct rpm_clk_resource *clk, int ctx, u32 rate)
+{
+ struct clk_smd_rpm_req req = {
+ .key = cpu_to_le32(QCOM_RPM_SMD_KEY_RATE),
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ };
+
+ /* Branch clocks are only on/off */
+ if (clk->branch)
+ rate = !!rate;
+
+ req.value = cpu_to_le32(rate);
+ return qcom_rpm_smd_write(icc_smd_rpm,
+ ctx,
+ clk->resource_type,
+ clk->clock_id,
+ &req, sizeof(req));
+}
+EXPORT_SYMBOL_GPL(qcom_icc_rpm_set_bus_rate);
+
static int qcom_icc_rpm_smd_remove(struct platform_device *pdev)
{
icc_smd_rpm = NULL;

--
2.41.0


2023-06-14 18:42:40

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 06/22] interconnect: qcom: icc-rpm: Introduce keep_alive

The downstream kernel employs the concept of "keeping the bus alive"
by voting for the minimum (XO/19.2MHz) rate at all times on certain
(well, most) buses. This is a very important thing to have, as if we
either have a lackluster/wrong DT that doesn't specify a (high enough)
vote on a certain bus, we may lose access to the entire bus altogether.
This is very apparent when we only start introducing interconnect
support on a given platform and haven't yet introduced voting on all
peripherals.

The same can happen if we only have a single driver casting a vote on
a certain bus and that driver exits/crashes/suspends.

The keepalive vote is limited to the ACTIVE bucket, as keeping a
permanent vote on the SLEEP one could prevent the platform from properly
entering low power mode states.

Introduce the very same concept, with a slight twist: the vendor
kernel checks whether the rate is zero before setting the minimum
vote, but that's rather silly, as in doing so we're at the mercy
of CCF. Instead, explicitly clamp the rates to always be >= 19.2 MHz
for providers with keep_alive=true.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 10 ++++++++++
drivers/interconnect/qcom/icc-rpm.h | 3 +++
2 files changed, 13 insertions(+)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 6acc7686ed38..863e8ba1daa2 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -50,6 +50,8 @@
#define NOC_QOS_MODE_FIXED_VAL 0x0
#define NOC_QOS_MODE_BYPASS_VAL 0x2

+#define ICC_BUS_CLK_MIN_RATE 19200000ULL
+
static int qcom_icc_set_qnoc_qos(struct icc_node *src)
{
struct icc_provider *provider = src->provider;
@@ -380,6 +382,13 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
do_div(rate, src_qn->buswidth);
rate = min_t(u64, rate, LONG_MAX);

+ /*
+ * Downstream checks whether the requested rate is zero, but it makes little sense
+ * to vote for a value that's below the lower threshold, so let's not do so.
+ */
+ if (bucket == QCOM_ICC_BUCKET_WAKE && qp->keep_alive)
+ rate = max(ICC_BUS_CLK_MIN_RATE, rate);
+
if (qp->bus_clk_rate[i] == rate)
continue;

@@ -453,6 +462,7 @@ int qnoc_probe(struct platform_device *pdev)
for (i = 0; i < qp->num_bus_clks; i++)
qp->bus_clks[i].id = bus_clocks[i];

+ qp->keep_alive = desc->keep_alive;
qp->type = desc->type;
qp->qos_offset = desc->qos_offset;

diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index ee705edf19dd..d2c04c400cad 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -33,6 +33,7 @@ enum qcom_icc_type {
* @bus_clk_rate: bus clock rate in Hz
* @bus_clks: the clk_bulk_data table of bus clocks
* @intf_clks: a clk_bulk_data array of interface clocks
+ * @keep_alive: whether to always keep a minimum vote on the bus clocks
* @is_on: whether the bus is powered on
*/
struct qcom_icc_provider {
@@ -45,6 +46,7 @@ struct qcom_icc_provider {
u64 bus_clk_rate[NUM_BUS_CLKS];
struct clk_bulk_data bus_clks[NUM_BUS_CLKS];
struct clk_bulk_data *intf_clks;
+ bool keep_alive;
bool is_on;
};

@@ -102,6 +104,7 @@ struct qcom_icc_desc {
const char * const *bus_clocks;
const char * const *intf_clocks;
size_t num_intf_clocks;
+ bool keep_alive;
bool no_clk_scaling;
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;

--
2.41.0


2023-06-14 18:43:00

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 11/22] interconnect: qcom: sdm660: Hook up RPM bus clk definitions

Assign the necessary definitions to migrate to the new bus clock
handling mechanism.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/sdm660.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index e7bd86808f13..ad5d52af7eab 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -1510,6 +1510,7 @@ static const struct qcom_icc_desc sdm660_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_a2noc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes),
+ .bus_clk_desc = &aggre2_clk,
.intf_clocks = a2noc_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &sdm660_a2noc_regmap_config,
@@ -1538,6 +1539,7 @@ static const struct qcom_icc_desc sdm660_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = sdm660_bimc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_bimc_nodes),
+ .bus_clk_desc = &bimc_clk,
.regmap_cfg = &sdm660_bimc_regmap_config,
};

@@ -1592,6 +1594,7 @@ static const struct qcom_icc_desc sdm660_cnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_cnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_cnoc_nodes),
+ .bus_clk_desc = &bus_2_clk,
.regmap_cfg = &sdm660_cnoc_regmap_config,
};

@@ -1654,6 +1657,7 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_mnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes),
+ .bus_clk_desc = &mmaxi_0_clk,
.intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config,
@@ -1691,6 +1695,7 @@ static const struct qcom_icc_desc sdm660_snoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_snoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_snoc_nodes),
+ .bus_clk_desc = &bus_1_clk,
.regmap_cfg = &sdm660_snoc_regmap_config,
};


--
2.41.0


2023-06-14 18:42:59

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 17/22] interconnect: qcom: icc-rpm: Control bus rpmcc from icc

The sole purpose of bus clocks that were previously registered with
rpmcc was to convey the aggregated bandwidth to RPM. There's no good
reason to keep them outside the interconnect framework, as it only
adds to the plentiful complexity.

Add the required code to handle these clocks from within SMD RPM ICC.

RPM-owned bus clocks are no longer considered a thing, but sadly we
have to allow for the existence of HLOS-owned bus clocks, as some
(mostly older) SoCs (ab)use these for bus scaling (e.g. MSM8998 and
&mmcc AHB_CLK_SRC).

This in turn is trivially solved with a single *clk, which is filled
and used iff qp.bus_clk_desc is absent and we have a "bus" clock-names
entry in the DT node.

This change should(tm) be fully compatible with all sorts of old
Device Trees as far as the interconnect functionality goes (modulo
abusing bus clock handles or wrongly using the qcom,icc.h binding,
but that's a mistake in and of itself).

Reviewed-by: Stephan Gerhold <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 121 ++++++++++++++++++++----------------
drivers/interconnect/qcom/icc-rpm.h | 13 ++--
drivers/interconnect/qcom/msm8996.c | 1 -
drivers/interconnect/qcom/sdm660.c | 1 -
4 files changed, 73 insertions(+), 63 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 3fdf3962b80d..60e4eab8855a 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -48,7 +48,7 @@
#define NOC_QOS_MODE_FIXED_VAL 0x0
#define NOC_QOS_MODE_BYPASS_VAL 0x2

-#define ICC_BUS_CLK_MIN_RATE 19200000ULL
+#define ICC_BUS_CLK_MIN_RATE 19200ULL /* kHz */

static int qcom_icc_set_qnoc_qos(struct icc_node *src)
{
@@ -337,11 +337,10 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
struct qcom_icc_node *src_qn = NULL, *dst_qn = NULL;
struct icc_provider *provider;
u64 sum_bw;
- u64 rate;
+ u64 active_rate, sleep_rate;
u64 agg_avg[QCOM_ICC_NUM_BUCKETS], agg_peak[QCOM_ICC_NUM_BUCKETS];
u64 max_agg_avg;
- int ret, i;
- int bucket;
+ int ret;

src_qn = src->data;
if (dst)
@@ -363,49 +362,61 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
return ret;
}

- for (i = 0; i < qp->num_bus_clks; i++) {
- /*
- * Use WAKE bucket for active clock, otherwise, use SLEEP bucket
- * for other clocks. If a platform doesn't set interconnect
- * path tags, by default use sleep bucket for all clocks.
- *
- * Note, AMC bucket is not supported yet.
- */
- if (!strcmp(qp->bus_clks[i].id, "bus_a"))
- bucket = QCOM_ICC_BUCKET_WAKE;
- else
- bucket = QCOM_ICC_BUCKET_SLEEP;
-
- rate = icc_units_to_bps(max(agg_avg[bucket], agg_peak[bucket]));
- do_div(rate, src_qn->buswidth);
- rate = min_t(u64, rate, LONG_MAX);
-
- /*
- * Downstream checks whether the requested rate is zero, but it makes little sense
- * to vote for a value that's below the lower threshold, so let's not do so.
- */
- if (bucket == QCOM_ICC_BUCKET_WAKE && qp->keep_alive)
- rate = max(ICC_BUS_CLK_MIN_RATE, rate);
-
- if (qp->bus_clk_rate[i] == rate)
- continue;
-
- ret = clk_set_rate(qp->bus_clks[i].clk, rate);
- if (ret) {
- pr_err("%s clk_set_rate error: %d\n",
- qp->bus_clks[i].id, ret);
+ /* Some providers don't have a bus clock to scale */
+ if (!qp->bus_clk_desc && !qp->bus_clk)
+ return 0;
+
+ /* Intentionally keep the rates in kHz as that's what RPM accepts */
+ active_rate = max(agg_avg[QCOM_SMD_RPM_ACTIVE_STATE],
+ agg_peak[QCOM_SMD_RPM_ACTIVE_STATE]);
+ do_div(active_rate, src_qn->buswidth);
+
+ sleep_rate = max(agg_avg[QCOM_SMD_RPM_SLEEP_STATE],
+ agg_peak[QCOM_SMD_RPM_SLEEP_STATE]);
+ do_div(sleep_rate, src_qn->buswidth);
+
+ /*
+ * Downstream checks whether the requested rate is zero, but it makes little sense
+ * to vote for a value that's below the lower threshold, so let's not do so.
+ */
+ if (qp->keep_alive)
+ active_rate = max(ICC_BUS_CLK_MIN_RATE, active_rate);
+
+ /* Some providers have a non-RPM-owned bus clock - convert kHz->Hz for the CCF */
+ if (qp->bus_clk) {
+ active_rate = max_t(u64, active_rate, sleep_rate);
+ /* ARM32 caps clk_set_rate arg to u32.. Nothing we can do about that! */
+ active_rate = min_t(u64, 1000ULL * active_rate, ULONG_MAX);
+ return clk_set_rate(qp->bus_clk, active_rate);
+ }
+
+ /* RPM only accepts <=INT_MAX rates */
+ active_rate = min_t(u64, active_rate, INT_MAX);
+ sleep_rate = min_t(u64, sleep_rate, INT_MAX);
+
+ if (active_rate != qp->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE]) {
+ ret = qcom_icc_rpm_set_bus_rate(qp->bus_clk_desc, QCOM_SMD_RPM_ACTIVE_STATE,
+ active_rate);
+ if (ret)
return ret;
- }
- qp->bus_clk_rate[i] = rate;
+
+ /* Cache the rate after we've successfully commited it to RPM */
+ qp->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE] = active_rate;
+ }
+
+ if (sleep_rate != qp->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE]) {
+ ret = qcom_icc_rpm_set_bus_rate(qp->bus_clk_desc, QCOM_SMD_RPM_SLEEP_STATE,
+ sleep_rate);
+ if (ret)
+ return ret;
+
+ /* Cache the rate after we've successfully commited it to RPM */
+ qp->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE] = sleep_rate;
}

return 0;
}

-static const char * const bus_clocks[] = {
- "bus", "bus_a",
-};
-
int qnoc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -447,6 +458,20 @@ int qnoc_probe(struct platform_device *pdev)
if (!qp->intf_clks)
return -ENOMEM;

+ if (desc->bus_clk_desc) {
+ qp->bus_clk_desc = devm_kzalloc(dev, sizeof(*qp->bus_clk_desc),
+ GFP_KERNEL);
+ if (!qp->bus_clk_desc)
+ return -ENOMEM;
+
+ qp->bus_clk_desc = desc->bus_clk_desc;
+ } else {
+ /* Some older SoCs may have a single non-RPM-owned bus clock. */
+ qp->bus_clk = devm_clk_get_optional(dev, "bus");
+ if (IS_ERR(qp->bus_clk))
+ return PTR_ERR(qp->bus_clk);
+ }
+
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
GFP_KERNEL);
if (!data)
@@ -456,10 +481,6 @@ int qnoc_probe(struct platform_device *pdev)
for (i = 0; i < cd_num; i++)
qp->intf_clks[i].id = cds[i];

- qp->num_bus_clks = desc->no_clk_scaling ? 0 : NUM_BUS_CLKS;
- for (i = 0; i < qp->num_bus_clks; i++)
- qp->bus_clks[i].id = bus_clocks[i];
-
qp->keep_alive = desc->keep_alive;
qp->type = desc->type;
qp->qos_offset = desc->qos_offset;
@@ -489,11 +510,7 @@ int qnoc_probe(struct platform_device *pdev)
}

regmap_done:
- ret = devm_clk_bulk_get(dev, qp->num_bus_clks, qp->bus_clks);
- if (ret)
- return ret;
-
- ret = clk_bulk_prepare_enable(qp->num_bus_clks, qp->bus_clks);
+ ret = clk_prepare_enable(qp->bus_clk);
if (ret)
return ret;

@@ -565,7 +582,7 @@ int qnoc_probe(struct platform_device *pdev)
icc_provider_deregister(provider);
err_remove_nodes:
icc_nodes_remove(provider);
- clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
+ clk_disable_unprepare(qp->bus_clk);

return ret;
}
@@ -577,7 +594,7 @@ int qnoc_remove(struct platform_device *pdev)

icc_provider_deregister(&qp->provider);
icc_nodes_remove(&qp->provider);
- clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
+ clk_disable_unprepare(qp->bus_clk);

return 0;
}
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index ecd6104335a7..e3b0aa9fff3e 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -37,32 +37,29 @@ struct rpm_clk_resource {
bool branch;
};

-#define NUM_BUS_CLKS 2
-
/**
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
- * @num_bus_clks: the total number of bus_clks clk_bulk_data entries (0 or 2)
* @num_intf_clks: the total number of intf_clks clk_bulk_data entries
* @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers
* @bus_clk_rate: bus clock rate in Hz
- * @bus_clks: the clk_bulk_data table of bus clocks
+ * @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks
+ * @bus_clk: a pointer to a HLOS-owned bus clock
* @intf_clks: a clk_bulk_data array of interface clocks
* @keep_alive: whether to always keep a minimum vote on the bus clocks
* @is_on: whether the bus is powered on
*/
struct qcom_icc_provider {
struct icc_provider provider;
- int num_bus_clks;
int num_intf_clks;
enum qcom_icc_type type;
struct regmap *regmap;
unsigned int qos_offset;
- u64 bus_clk_rate[NUM_BUS_CLKS];
- struct clk_bulk_data bus_clks[NUM_BUS_CLKS];
+ u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
const struct rpm_clk_resource *bus_clk_desc;
+ struct clk *bus_clk;
struct clk_bulk_data *intf_clks;
bool keep_alive;
bool is_on;
@@ -119,12 +116,10 @@ struct qcom_icc_node {
struct qcom_icc_desc {
struct qcom_icc_node * const *nodes;
size_t num_nodes;
- const char * const *bus_clocks;
const struct rpm_clk_resource *bus_clk_desc;
const char * const *intf_clocks;
size_t num_intf_clocks;
bool keep_alive;
- bool no_clk_scaling;
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;
unsigned int qos_offset;
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 42722681b4ce..b9695c1931ce 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -1817,7 +1817,6 @@ static const struct qcom_icc_desc msm8996_a0noc = {
.num_nodes = ARRAY_SIZE(a0noc_nodes),
.intf_clocks = a0noc_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
- .no_clk_scaling = true,
.regmap_cfg = &msm8996_a0noc_regmap_config
};

diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index ad5d52af7eab..e1aed937c86b 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -1617,7 +1617,6 @@ static const struct qcom_icc_desc sdm660_gnoc = {
.nodes = sdm660_gnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_gnoc_nodes),
.regmap_cfg = &sdm660_gnoc_regmap_config,
- .no_clk_scaling = true,
};

static struct qcom_icc_node * const sdm660_mnoc_nodes[] = {

--
2.41.0


2023-06-14 18:43:00

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 05/22] soc: qcom: smd-rpm: Move icc_smd_rpm registration to clk-smd-rpm

From: Stephan Gerhold <[email protected]>

icc_smd_rpm will do bus clock votes itself rather than taking the
unnecessary detour through the clock subsystem. However, it can only
do that after the clocks have been handed off and scaling has been
enabled in the RPM in clk-smd-rpm.

Move the icc_smd_rpm registration from smd-rpm.c to clk-smd-rpm.c
to avoid any possible races. icc_smd_rpm gets the driver data from
the smd-rpm device, so still register the platform device on the
smd-rpm parent device.

Signed-off-by: Stephan Gerhold <[email protected]>
[Konrad: remove unrelated cleanups]
Acked-by: Stephen Boyd <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/clk/qcom/clk-smd-rpm.c | 21 +++++++++++++++++++++
drivers/soc/qcom/smd-rpm.c | 17 +----------------
2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index 937cb1515968..6e7f0438e8b8 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -1289,12 +1289,20 @@ static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec,
return desc->clks[idx] ? &desc->clks[idx]->hw : ERR_PTR(-ENOENT);
}

+static void rpm_smd_unregister_icc(void *data)
+{
+ struct platform_device *icc_pdev = data;
+
+ platform_device_unregister(icc_pdev);
+}
+
static int rpm_smd_clk_probe(struct platform_device *pdev)
{
int ret;
size_t num_clks, i;
struct clk_smd_rpm **rpm_smd_clks;
const struct rpm_smd_clk_desc *desc;
+ struct platform_device *icc_pdev;

rpmcc_smd_rpm = dev_get_drvdata(pdev->dev.parent);
if (!rpmcc_smd_rpm) {
@@ -1344,6 +1352,19 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
if (ret)
goto err;

+ icc_pdev = platform_device_register_data(pdev->dev.parent,
+ "icc_smd_rpm", -1, NULL, 0);
+ if (IS_ERR(icc_pdev)) {
+ dev_err(&pdev->dev, "Failed to register icc_smd_rpm device: %pE\n",
+ icc_pdev);
+ /* No need to unregister clocks because of this */
+ } else {
+ ret = devm_add_action_or_reset(&pdev->dev, rpm_smd_unregister_icc,
+ icc_pdev);
+ if (ret)
+ goto err;
+ }
+
return 0;
err:
dev_err(&pdev->dev, "Error registering SMD clock driver (%d)\n", ret);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 0c1aa809cc4e..577f1f25ab10 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -19,7 +19,6 @@
/**
* struct qcom_smd_rpm - state of the rpm device driver
* @rpm_channel: reference to the smd channel
- * @icc: interconnect proxy device
* @dev: rpm device
* @ack: completion for acks
* @lock: mutual exclusion around the send/complete pair
@@ -27,7 +26,6 @@
*/
struct qcom_smd_rpm {
struct rpmsg_endpoint *rpm_channel;
- struct platform_device *icc;
struct device *dev;

struct completion ack;
@@ -197,7 +195,6 @@ static int qcom_smd_rpm_callback(struct rpmsg_device *rpdev,
static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
{
struct qcom_smd_rpm *rpm;
- int ret;

rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL);
if (!rpm)
@@ -210,23 +207,11 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
rpm->rpm_channel = rpdev->ept;
dev_set_drvdata(&rpdev->dev, rpm);

- rpm->icc = platform_device_register_data(&rpdev->dev, "icc_smd_rpm", -1,
- NULL, 0);
- if (IS_ERR(rpm->icc))
- return PTR_ERR(rpm->icc);
-
- ret = of_platform_populate(rpdev->dev.of_node, NULL, NULL, &rpdev->dev);
- if (ret)
- platform_device_unregister(rpm->icc);
-
- return ret;
+ return of_platform_populate(rpdev->dev.of_node, NULL, NULL, &rpdev->dev);
}

static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
{
- struct qcom_smd_rpm *rpm = dev_get_drvdata(&rpdev->dev);
-
- platform_device_unregister(rpm->icc);
of_platform_depopulate(&rpdev->dev);
}


--
2.41.0


2023-06-14 18:43:12

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v6 08/22] interconnect: qcom: Fold smd-rpm.h into icc-rpm.h

smd-rpm.h is not very useful as-is and both files are always included
anyway.. Combine them.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 1 -
drivers/interconnect/qcom/icc-rpm.h | 5 +++++
drivers/interconnect/qcom/msm8916.c | 1 -
drivers/interconnect/qcom/msm8939.c | 1 -
drivers/interconnect/qcom/msm8974.c | 2 +-
drivers/interconnect/qcom/msm8996.c | 1 -
drivers/interconnect/qcom/qcm2290.c | 1 -
drivers/interconnect/qcom/qcs404.c | 1 -
drivers/interconnect/qcom/sdm660.c | 1 -
drivers/interconnect/qcom/smd-rpm.c | 2 +-
drivers/interconnect/qcom/smd-rpm.h | 15 ---------------
11 files changed, 7 insertions(+), 24 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 80409f59b2c8..3fdf3962b80d 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -13,7 +13,6 @@
#include <linux/regmap.h>
#include <linux/slab.h>

-#include "smd-rpm.h"
#include "icc-common.h"
#include "icc-rpm.h"

diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 899e75e8ebaf..4755e422d2d1 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -6,6 +6,8 @@
#ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H
#define __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H

+#include <linux/soc/qcom/smd-rpm.h>
+
#include <dt-bindings/interconnect/qcom,icc.h>
#include <linux/clk.h>
#include <linux/interconnect-provider.h>
@@ -124,4 +126,7 @@ enum qos_mode {
int qnoc_probe(struct platform_device *pdev);
int qnoc_remove(struct platform_device *pdev);

+bool qcom_icc_rpm_smd_available(void);
+int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val);
+
#endif
diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c
index 518f4b40ecc2..70b67fbe453f 100644
--- a/drivers/interconnect/qcom/msm8916.c
+++ b/drivers/interconnect/qcom/msm8916.c
@@ -14,7 +14,6 @@

#include <dt-bindings/interconnect/qcom,msm8916.h>

-#include "smd-rpm.h"
#include "icc-rpm.h"

enum {
diff --git a/drivers/interconnect/qcom/msm8939.c b/drivers/interconnect/qcom/msm8939.c
index a7398c3c7411..b1005dee4e38 100644
--- a/drivers/interconnect/qcom/msm8939.c
+++ b/drivers/interconnect/qcom/msm8939.c
@@ -15,7 +15,6 @@

#include <dt-bindings/interconnect/qcom,msm8939.h>

-#include "smd-rpm.h"
#include "icc-rpm.h"

enum {
diff --git a/drivers/interconnect/qcom/msm8974.c b/drivers/interconnect/qcom/msm8974.c
index 1828deaca443..968162213d40 100644
--- a/drivers/interconnect/qcom/msm8974.c
+++ b/drivers/interconnect/qcom/msm8974.c
@@ -38,7 +38,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>

-#include "smd-rpm.h"
+#include "icc-rpm.h"

enum {
MSM8974_BIMC_MAS_AMPSS_M0 = 1,
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 733213a0b8c1..b03b1d454a41 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -17,7 +17,6 @@
#include <dt-bindings/interconnect/qcom,msm8996.h>

#include "icc-rpm.h"
-#include "smd-rpm.h"
#include "msm8996.h"

static const char * const mm_intf_clocks[] = {
diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c
index 95ea1f6d25ba..36a53add866d 100644
--- a/drivers/interconnect/qcom/qcm2290.c
+++ b/drivers/interconnect/qcom/qcm2290.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>

#include "icc-rpm.h"
-#include "smd-rpm.h"

enum {
QCM2290_MASTER_APPSS_PROC = 1,
diff --git a/drivers/interconnect/qcom/qcs404.c b/drivers/interconnect/qcom/qcs404.c
index 9292f8ac01b8..1faec0af74e7 100644
--- a/drivers/interconnect/qcom/qcs404.c
+++ b/drivers/interconnect/qcom/qcs404.c
@@ -12,7 +12,6 @@
#include <linux/of_device.h>


-#include "smd-rpm.h"
#include "icc-rpm.h"

enum {
diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index 904014a9fd32..e7bd86808f13 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -16,7 +16,6 @@
#include <linux/slab.h>

#include "icc-rpm.h"
-#include "smd-rpm.h"

enum {
SDM660_MASTER_IPA = 1,
diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c
index dc8ff8d133a9..b0183262ba66 100644
--- a/drivers/interconnect/qcom/smd-rpm.c
+++ b/drivers/interconnect/qcom/smd-rpm.c
@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/soc/qcom/smd-rpm.h>

-#include "smd-rpm.h"
+#include "icc-rpm.h"

#define RPM_KEY_BW 0x00007762

diff --git a/drivers/interconnect/qcom/smd-rpm.h b/drivers/interconnect/qcom/smd-rpm.h
deleted file mode 100644
index ca9d0327b8ac..000000000000
--- a/drivers/interconnect/qcom/smd-rpm.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2019, Linaro Ltd.
- * Author: Georgi Djakov <[email protected]>
- */
-
-#ifndef __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H
-#define __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H
-
-#include <linux/soc/qcom/smd-rpm.h>
-
-bool qcom_icc_rpm_smd_available(void);
-int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val);
-
-#endif

--
2.41.0


2023-06-15 00:52:16

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v6 00/22] Restructure RPM SMD ICC

Quoting Konrad Dybcio (2023-06-14 11:04:19)
> This series reshuffles things around, moving the management of SMD RPM
> bus clocks to the interconnect framework where they belong. This helps
> us solve a couple of issues:
>
> 1. We can work towards unused clk cleanup of RPMCC without worrying
> about it killing some NoC bus, resulting in the SoC dying.
> Deasserting actually unused RPM clocks (among other things) will
> let us achieve "true SoC-wide power collapse states", also known as
> VDD_LOW and VDD_MIN.
>
> 2. We no longer have to keep tons of quirky bus clock ifs in the icc
> driver. You either have a RPM clock and call "rpm set rate" or you
> have a single non-RPM clock (like AHB_CLK_SRC) or you don't have any.
>
> 3. There's less overhead - instead of going through layers and layers of
> the CCF, ratesetting comes down to calling max() and sending a single
> RPM message. ICC is very very dynamic so that's a big plus.
>
> The clocks still need to be vaguely described in the clk-smd-rpm driver,
> as it gives them an initial kickoff, before actually telling RPM to
> enable DVFS scaling. After RPM receives that command, all clocks that
> have not been assigned a rate are considered unused and are shut down
> in hardware, leading to the same issue as described in point 1.

Why can't we move the enable of DVFS scaling call to the interconnect
driver as well? We want the clk driver to not reference the interconnect
resources at all.

2023-06-15 08:03:09

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH v6 00/22] Restructure RPM SMD ICC

On 15.06.2023 02:49, Stephen Boyd wrote:
> Quoting Konrad Dybcio (2023-06-14 11:04:19)
>> This series reshuffles things around, moving the management of SMD RPM
>> bus clocks to the interconnect framework where they belong. This helps
>> us solve a couple of issues:
>>
>> 1. We can work towards unused clk cleanup of RPMCC without worrying
>> about it killing some NoC bus, resulting in the SoC dying.
>> Deasserting actually unused RPM clocks (among other things) will
>> let us achieve "true SoC-wide power collapse states", also known as
>> VDD_LOW and VDD_MIN.
>>
>> 2. We no longer have to keep tons of quirky bus clock ifs in the icc
>> driver. You either have a RPM clock and call "rpm set rate" or you
>> have a single non-RPM clock (like AHB_CLK_SRC) or you don't have any.
>>
>> 3. There's less overhead - instead of going through layers and layers of
>> the CCF, ratesetting comes down to calling max() and sending a single
>> RPM message. ICC is very very dynamic so that's a big plus.
>>
>> The clocks still need to be vaguely described in the clk-smd-rpm driver,
>> as it gives them an initial kickoff, before actually telling RPM to
>> enable DVFS scaling. After RPM receives that command, all clocks that
>> have not been assigned a rate are considered unused and are shut down
>> in hardware, leading to the same issue as described in point 1.
>
> Why can't we move the enable of DVFS scaling call to the interconnect
> driver as well? We want the clk driver to not reference the interconnect
> resources at all.
That would result in no rpmcc ratesetting on platforms without a functional
interconnect driver. The DVFS call concerns both bus and !bus clocks.

Konrad

2023-06-15 17:43:23

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v6 00/22] Restructure RPM SMD ICC

Quoting Konrad Dybcio (2023-06-15 00:52:07)
> On 15.06.2023 02:49, Stephen Boyd wrote:
> > Quoting Konrad Dybcio (2023-06-14 11:04:19)
> >> This series reshuffles things around, moving the management of SMD RPM
> >> bus clocks to the interconnect framework where they belong. This helps
> >> us solve a couple of issues:
> >>
> >> 1. We can work towards unused clk cleanup of RPMCC without worrying
> >> about it killing some NoC bus, resulting in the SoC dying.
> >> Deasserting actually unused RPM clocks (among other things) will
> >> let us achieve "true SoC-wide power collapse states", also known as
> >> VDD_LOW and VDD_MIN.
> >>
> >> 2. We no longer have to keep tons of quirky bus clock ifs in the icc
> >> driver. You either have a RPM clock and call "rpm set rate" or you
> >> have a single non-RPM clock (like AHB_CLK_SRC) or you don't have any.
> >>
> >> 3. There's less overhead - instead of going through layers and layers of
> >> the CCF, ratesetting comes down to calling max() and sending a single
> >> RPM message. ICC is very very dynamic so that's a big plus.
> >>
> >> The clocks still need to be vaguely described in the clk-smd-rpm driver,
> >> as it gives them an initial kickoff, before actually telling RPM to
> >> enable DVFS scaling. After RPM receives that command, all clocks that
> >> have not been assigned a rate are considered unused and are shut down
> >> in hardware, leading to the same issue as described in point 1.
> >
> > Why can't we move the enable of DVFS scaling call to the interconnect
> > driver as well? We want the clk driver to not reference the interconnect
> > resources at all.
> That would result in no rpmcc ratesetting on platforms without a functional
> interconnect driver. The DVFS call concerns both bus and !bus clocks.
>

That's the intent. Probe the interconnect driver to get bus clk rate
setting.

What are the !bus clocks managed by RPM?

2023-06-15 18:04:24

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH v6 00/22] Restructure RPM SMD ICC

On 15.06.2023 19:35, Stephen Boyd wrote:
> Quoting Konrad Dybcio (2023-06-15 00:52:07)
>> On 15.06.2023 02:49, Stephen Boyd wrote:
>>> Quoting Konrad Dybcio (2023-06-14 11:04:19)
>>>> This series reshuffles things around, moving the management of SMD RPM
>>>> bus clocks to the interconnect framework where they belong. This helps
>>>> us solve a couple of issues:
>>>>
>>>> 1. We can work towards unused clk cleanup of RPMCC without worrying
>>>> about it killing some NoC bus, resulting in the SoC dying.
>>>> Deasserting actually unused RPM clocks (among other things) will
>>>> let us achieve "true SoC-wide power collapse states", also known as
>>>> VDD_LOW and VDD_MIN.
>>>>
>>>> 2. We no longer have to keep tons of quirky bus clock ifs in the icc
>>>> driver. You either have a RPM clock and call "rpm set rate" or you
>>>> have a single non-RPM clock (like AHB_CLK_SRC) or you don't have any.
>>>>
>>>> 3. There's less overhead - instead of going through layers and layers of
>>>> the CCF, ratesetting comes down to calling max() and sending a single
>>>> RPM message. ICC is very very dynamic so that's a big plus.
>>>>
>>>> The clocks still need to be vaguely described in the clk-smd-rpm driver,
>>>> as it gives them an initial kickoff, before actually telling RPM to
>>>> enable DVFS scaling. After RPM receives that command, all clocks that
>>>> have not been assigned a rate are considered unused and are shut down
>>>> in hardware, leading to the same issue as described in point 1.
>>>
>>> Why can't we move the enable of DVFS scaling call to the interconnect
>>> driver as well? We want the clk driver to not reference the interconnect
>>> resources at all.
>> That would result in no rpmcc ratesetting on platforms without a functional
>> interconnect driver. The DVFS call concerns both bus and !bus clocks.
>>
>
> That's the intent. Probe the interconnect driver to get bus clk rate
> setting.
>
> What are the !bus clocks managed by RPM?
Depending on the platform, that includes IPA, GPU, OCMEM, RF.. everything
that's not been separated out in patch 18.

Konrad