]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
interconnect: qcom: msm8974: switch to the main icc-rpm driver
authorDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Tue, 24 Mar 2026 00:10:43 +0000 (02:10 +0200)
committerGeorgi Djakov <djakov@kernel.org>
Thu, 26 Mar 2026 18:09:55 +0000 (20:09 +0200)
In preparation to restoring the ability of MSM8974 driver to work with
the modern kernels, switch the driver to the main icc-rpm set of helper
code.

As platform-specific workarounds, set the get_bw callback (returning 0)
to prevent initial setup from programming INT_MAX into the RPM (which
otherwise might hang the platform) and tell RPM programming code to
ignore -ENXIO errors from the firmware (until the QoS programming is
sorted out).

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://msgid.link/20260324-msm8974-icc-v2-7-527280043ad8@oss.qualcomm.com
Signed-off-by: Georgi Djakov <djakov@kernel.org>
drivers/interconnect/qcom/msm8974.c

index 3239edc37f02f20bd65fbbcb4aa48dc7953c7c09..144f225ec88579a609b80d1de13d5502a86d99cc 100644 (file)
@@ -173,65 +173,27 @@ enum {
        MSM8974_SNOC_SLV_QDSS_STM,
 };
 
-#define to_msm8974_icc_provider(_provider) \
-       container_of(_provider, struct msm8974_icc_provider, provider)
-
-static const struct clk_bulk_data msm8974_icc_bus_clocks[] = {
-       { .id = "bus" },
-       { .id = "bus_a" },
-};
-
-/**
- * struct msm8974_icc_provider - Qualcomm specific interconnect provider
- * @provider: generic interconnect provider
- * @bus_clks: the clk_bulk_data table of bus clocks
- * @num_clks: the total number of clk_bulk_data entries
- */
-struct msm8974_icc_provider {
-       struct icc_provider provider;
-       struct clk_bulk_data *bus_clks;
-       int num_clks;
-};
-
-#define MSM8974_ICC_MAX_LINKS  3
-
-/**
- * struct msm8974_icc_node - Qualcomm specific interconnect nodes
- * @name: the node name used in debugfs
- * @id: a unique node identifier
- * @links: an array of nodes where we can go next while traversing
- * @num_links: the total number of @links
- * @buswidth: width of the interconnect between a node and the bus (bytes)
- * @mas_rpm_id:        RPM ID for devices that are bus masters
- * @slv_rpm_id:        RPM ID for devices that are bus slaves
- * @rate: current bus clock rate in Hz
- */
-struct msm8974_icc_node {
-       unsigned char *name;
-       u16 id;
-       u16 links[MSM8974_ICC_MAX_LINKS];
-       u16 num_links;
-       u16 buswidth;
-       int mas_rpm_id;
-       int slv_rpm_id;
-       u64 rate;
-};
+static int msm8974_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+       *avg = 0;
+       *peak = 0;
 
-struct msm8974_icc_desc {
-       struct msm8974_icc_node * const *nodes;
-       size_t num_nodes;
+       return 0;
 };
 
 #define DEFINE_QNODE(_name, _id, _buswidth, _mas_rpm_id, _slv_rpm_id,  \
                     ...)                                               \
-               static struct msm8974_icc_node _name = {                \
+               static const u16 _name ## _links[] = {                  \
+                       __VA_ARGS__                                     \
+               };                                                      \
+               static struct qcom_icc_node _name = {                   \
                .name = #_name,                                         \
                .id = _id,                                              \
                .buswidth = _buswidth,                                  \
                .mas_rpm_id = _mas_rpm_id,                              \
                .slv_rpm_id = _slv_rpm_id,                              \
-               .num_links = COUNT_ARGS(__VA_ARGS__),                   \
-               .links = { __VA_ARGS__ },                               \
+               .num_links = ARRAY_SIZE(_name ## _links),               \
+               .links = _name ## _links,                               \
        }
 
 DEFINE_QNODE(mas_ampss_m0, MSM8974_BIMC_MAS_AMPSS_M0, 8, 0, -1);
@@ -242,7 +204,7 @@ DEFINE_QNODE(bimc_to_snoc, MSM8974_BIMC_TO_SNOC, 8, 3, 2, MSM8974_SNOC_TO_BIMC,
 DEFINE_QNODE(slv_ebi_ch0, MSM8974_BIMC_SLV_EBI_CH0, 8, -1, 0);
 DEFINE_QNODE(slv_ampss_l2, MSM8974_BIMC_SLV_AMPSS_L2, 8, -1, 1);
 
-static struct msm8974_icc_node * const msm8974_bimc_nodes[] = {
+static struct qcom_icc_node * const msm8974_bimc_nodes[] = {
        [BIMC_MAS_AMPSS_M0] = &mas_ampss_m0,
        [BIMC_MAS_AMPSS_M1] = &mas_ampss_m1,
        [BIMC_MAS_MSS_PROC] = &mas_mss_proc,
@@ -252,9 +214,12 @@ static struct msm8974_icc_node * const msm8974_bimc_nodes[] = {
        [BIMC_SLV_AMPSS_L2] = &slv_ampss_l2,
 };
 
-static const struct msm8974_icc_desc msm8974_bimc = {
+static const struct qcom_icc_desc msm8974_bimc = {
        .nodes = msm8974_bimc_nodes,
        .num_nodes = ARRAY_SIZE(msm8974_bimc_nodes),
+       .bus_clk_desc = &bimc_clk,
+       .get_bw = msm8974_get_bw,
+       .ignore_enxio = true,
 };
 
 DEFINE_QNODE(mas_rpm_inst, MSM8974_CNOC_MAS_RPM_INST, 8, 45, -1);
@@ -295,7 +260,7 @@ DEFINE_QNODE(slv_ebi1_phy_cfg, MSM8974_CNOC_SLV_EBI1_PHY_CFG, 8, -1, 73);
 DEFINE_QNODE(slv_rpm, MSM8974_CNOC_SLV_RPM, 8, -1, 74);
 DEFINE_QNODE(slv_service_cnoc, MSM8974_CNOC_SLV_SERVICE_CNOC, 8, -1, 76);
 
-static struct msm8974_icc_node * const msm8974_cnoc_nodes[] = {
+static struct qcom_icc_node * const msm8974_cnoc_nodes[] = {
        [CNOC_MAS_RPM_INST] = &mas_rpm_inst,
        [CNOC_MAS_RPM_DATA] = &mas_rpm_data,
        [CNOC_MAS_RPM_SYS] = &mas_rpm_sys,
@@ -335,9 +300,12 @@ static struct msm8974_icc_node * const msm8974_cnoc_nodes[] = {
        [CNOC_SLV_SERVICE_CNOC] = &slv_service_cnoc,
 };
 
-static const struct msm8974_icc_desc msm8974_cnoc = {
+static const struct qcom_icc_desc msm8974_cnoc = {
        .nodes = msm8974_cnoc_nodes,
        .num_nodes = ARRAY_SIZE(msm8974_cnoc_nodes),
+       .bus_clk_desc = &bus_2_clk,
+       .get_bw = msm8974_get_bw,
+       .ignore_enxio = true,
 };
 
 DEFINE_QNODE(mas_graphics_3d, MSM8974_MNOC_MAS_GRAPHICS_3D, 16, 6, -1, MSM8974_MNOC_TO_BIMC);
@@ -363,7 +331,7 @@ DEFINE_QNODE(slv_mnoc_mpu_cfg, MSM8974_MNOC_SLV_MNOC_MPU_CFG, 16, -1, 14);
 DEFINE_QNODE(slv_onoc_mpu_cfg, MSM8974_MNOC_SLV_ONOC_MPU_CFG, 16, -1, 15);
 DEFINE_QNODE(slv_service_mnoc, MSM8974_MNOC_SLV_SERVICE_MNOC, 16, -1, 17);
 
-static struct msm8974_icc_node * const msm8974_mnoc_nodes[] = {
+static struct qcom_icc_node * const msm8974_mnoc_nodes[] = {
        [MNOC_MAS_GRAPHICS_3D] = &mas_graphics_3d,
        [MNOC_MAS_JPEG] = &mas_jpeg,
        [MNOC_MAS_MDP_PORT0] = &mas_mdp_port0,
@@ -388,9 +356,11 @@ static struct msm8974_icc_node * const msm8974_mnoc_nodes[] = {
        [MNOC_SLV_SERVICE_MNOC] = &slv_service_mnoc,
 };
 
-static const struct msm8974_icc_desc msm8974_mnoc = {
+static const struct qcom_icc_desc msm8974_mnoc = {
        .nodes = msm8974_mnoc_nodes,
        .num_nodes = ARRAY_SIZE(msm8974_mnoc_nodes),
+       .get_bw = msm8974_get_bw,
+       .ignore_enxio = true,
 };
 
 DEFINE_QNODE(ocmem_noc_to_ocmem_vnoc, MSM8974_OCMEM_NOC_TO_OCMEM_VNOC, 16, 54, 78, MSM8974_OCMEM_SLV_OCMEM);
@@ -408,7 +378,7 @@ DEFINE_QNODE(ocmem_vnoc_to_onoc, MSM8974_OCMEM_VNOC_TO_OCMEM_NOC, 16, 56, 79, MS
 DEFINE_QNODE(ocmem_vnoc_to_snoc, MSM8974_OCMEM_VNOC_TO_SNOC, 8, 57, 80);
 DEFINE_QNODE(mas_v_ocmem_gfx3d, MSM8974_OCMEM_VNOC_MAS_GFX3D, 8, 55, -1, MSM8974_OCMEM_VNOC_TO_OCMEM_NOC);
 
-static struct msm8974_icc_node * const msm8974_onoc_nodes[] = {
+static struct qcom_icc_node * const msm8974_onoc_nodes[] = {
        [OCMEM_NOC_TO_OCMEM_VNOC] = &ocmem_noc_to_ocmem_vnoc,
        [OCMEM_MAS_JPEG_OCMEM] = &mas_jpeg_ocmem,
        [OCMEM_MAS_MDP_OCMEM] = &mas_mdp_ocmem,
@@ -423,9 +393,12 @@ static struct msm8974_icc_node * const msm8974_onoc_nodes[] = {
        [OCMEM_SLV_OCMEM] = &slv_ocmem,
 };
 
-static const struct msm8974_icc_desc msm8974_onoc = {
+static const struct qcom_icc_desc msm8974_onoc = {
        .nodes = msm8974_onoc_nodes,
        .num_nodes = ARRAY_SIZE(msm8974_onoc_nodes),
+       .bus_clk_desc = &gpu_mem_2_clk,
+       .get_bw = msm8974_get_bw,
+       .ignore_enxio = true,
 };
 
 DEFINE_QNODE(mas_pnoc_cfg, MSM8974_PNOC_MAS_PNOC_CFG, 8, 43, -1);
@@ -456,7 +429,7 @@ DEFINE_QNODE(slv_pnoc_mpu_cfg, MSM8974_PNOC_SLV_PNOC_MPU_CFG, 8, -1, 43);
 DEFINE_QNODE(slv_prng, MSM8974_PNOC_SLV_PRNG, 8, -1, 44, MSM8974_PNOC_TO_SNOC);
 DEFINE_QNODE(slv_service_pnoc, MSM8974_PNOC_SLV_SERVICE_PNOC, 8, -1, 46);
 
-static struct msm8974_icc_node * const msm8974_pnoc_nodes[] = {
+static struct qcom_icc_node * const msm8974_pnoc_nodes[] = {
        [PNOC_MAS_PNOC_CFG] = &mas_pnoc_cfg,
        [PNOC_MAS_SDCC_1] = &mas_sdcc_1,
        [PNOC_MAS_SDCC_3] = &mas_sdcc_3,
@@ -486,9 +459,13 @@ static struct msm8974_icc_node * const msm8974_pnoc_nodes[] = {
        [PNOC_SLV_SERVICE_PNOC] = &slv_service_pnoc,
 };
 
-static const struct msm8974_icc_desc msm8974_pnoc = {
+static const struct qcom_icc_desc msm8974_pnoc = {
        .nodes = msm8974_pnoc_nodes,
        .num_nodes = ARRAY_SIZE(msm8974_pnoc_nodes),
+       .bus_clk_desc = &bus_0_clk,
+       .get_bw = msm8974_get_bw,
+       .keep_alive = true,
+       .ignore_enxio = true,
 };
 
 DEFINE_QNODE(mas_lpass_ahb, MSM8974_SNOC_MAS_LPASS_AHB, 8, 18, -1);
@@ -516,7 +493,7 @@ DEFINE_QNODE(slv_snoc_ocmem, MSM8974_SNOC_SLV_SNOC_OCMEM, 8, -1, 27);
 DEFINE_QNODE(slv_service_snoc, MSM8974_SNOC_SLV_SERVICE_SNOC, 8, -1, 29);
 DEFINE_QNODE(slv_qdss_stm, MSM8974_SNOC_SLV_QDSS_STM, 8, -1, 30);
 
-static struct msm8974_icc_node * const msm8974_snoc_nodes[] = {
+static struct qcom_icc_node * const msm8974_snoc_nodes[] = {
        [SNOC_MAS_LPASS_AHB] = &mas_lpass_ahb,
        [SNOC_MAS_QDSS_BAM] = &mas_qdss_bam,
        [SNOC_MAS_SNOC_CFG] = &mas_snoc_cfg,
@@ -543,209 +520,14 @@ static struct msm8974_icc_node * const msm8974_snoc_nodes[] = {
        [SNOC_SLV_QDSS_STM] = &slv_qdss_stm,
 };
 
-static const struct msm8974_icc_desc msm8974_snoc = {
+static const struct qcom_icc_desc msm8974_snoc = {
        .nodes = msm8974_snoc_nodes,
        .num_nodes = ARRAY_SIZE(msm8974_snoc_nodes),
+       .bus_clk_desc = &bus_1_clk,
+       .get_bw = msm8974_get_bw,
+       .ignore_enxio = true,
 };
 
-static void msm8974_icc_rpm_smd_send(struct device *dev, int rsc_type,
-                                    char *name, int id, u64 val)
-{
-       int ret;
-
-       if (id == -1)
-               return;
-
-       /*
-        * Setting the bandwidth requests for some nodes fails and this same
-        * behavior occurs on the downstream MSM 3.4 kernel sources based on
-        * errors like this in that kernel:
-        *
-        *   msm_rpm_get_error_from_ack(): RPM NACK Unsupported resource
-        *   AXI: msm_bus_rpm_req(): RPM: Ack failed
-        *   AXI: msm_bus_rpm_commit_arb(): RPM: Req fail: mas:32, bw:240000000
-        *
-        * Since there's no publicly available documentation for this hardware,
-        * and the bandwidth for some nodes in the path can be set properly,
-        * let's not return an error.
-        */
-       ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, rsc_type, id,
-                                   val);
-       if (ret)
-               dev_dbg(dev, "Cannot set bandwidth for node %s (%d): %d\n",
-                       name, id, ret);
-}
-
-static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst)
-{
-       struct msm8974_icc_node *src_qn, *dst_qn;
-       struct msm8974_icc_provider *qp;
-       u64 sum_bw, max_peak_bw, rate;
-       u32 agg_avg = 0, agg_peak = 0;
-       struct icc_provider *provider;
-       struct icc_node *n;
-       int ret, i;
-
-       src_qn = src->data;
-       dst_qn = dst->data;
-       provider = src->provider;
-       qp = to_msm8974_icc_provider(provider);
-
-       list_for_each_entry(n, &provider->nodes, node_list)
-               provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
-                                   &agg_avg, &agg_peak);
-
-       sum_bw = icc_units_to_bps(agg_avg);
-       max_peak_bw = icc_units_to_bps(agg_peak);
-
-       /* Set bandwidth on source node */
-       msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_MASTER_REQ,
-                                src_qn->name, src_qn->mas_rpm_id, sum_bw);
-
-       msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_SLAVE_REQ,
-                                src_qn->name, src_qn->slv_rpm_id, sum_bw);
-
-       /* Set bandwidth on destination node */
-       msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_MASTER_REQ,
-                                dst_qn->name, dst_qn->mas_rpm_id, sum_bw);
-
-       msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_SLAVE_REQ,
-                                dst_qn->name, dst_qn->slv_rpm_id, sum_bw);
-
-       rate = max(sum_bw, max_peak_bw);
-
-       do_div(rate, src_qn->buswidth);
-
-       rate = min_t(u32, rate, INT_MAX);
-
-       if (src_qn->rate == rate)
-               return 0;
-
-       for (i = 0; i < qp->num_clks; i++) {
-               ret = clk_set_rate(qp->bus_clks[i].clk, rate);
-               if (ret) {
-                       dev_err(provider->dev, "%s clk_set_rate error: %d\n",
-                               qp->bus_clks[i].id, ret);
-                       ret = 0;
-               }
-       }
-
-       src_qn->rate = rate;
-
-       return 0;
-}
-
-static int msm8974_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
-{
-       *avg = 0;
-       *peak = 0;
-
-       return 0;
-}
-
-static int msm8974_icc_probe(struct platform_device *pdev)
-{
-       const struct msm8974_icc_desc *desc;
-       struct msm8974_icc_node * const *qnodes;
-       struct msm8974_icc_provider *qp;
-       struct device *dev = &pdev->dev;
-       struct icc_onecell_data *data;
-       struct icc_provider *provider;
-       struct icc_node *node;
-       size_t num_nodes, i;
-       int ret;
-
-       /* wait for the RPM proxy */
-       if (!qcom_icc_rpm_smd_available())
-               return -EPROBE_DEFER;
-
-       desc = of_device_get_match_data(dev);
-       if (!desc)
-               return -EINVAL;
-
-       qnodes = desc->nodes;
-       num_nodes = desc->num_nodes;
-
-       qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
-       if (!qp)
-               return -ENOMEM;
-
-       data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
-                           GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       data->num_nodes = num_nodes;
-
-       qp->bus_clks = devm_kmemdup(dev, msm8974_icc_bus_clocks,
-                                   sizeof(msm8974_icc_bus_clocks), GFP_KERNEL);
-       if (!qp->bus_clks)
-               return -ENOMEM;
-
-       qp->num_clks = ARRAY_SIZE(msm8974_icc_bus_clocks);
-       ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
-       if (ret)
-               return ret;
-
-       ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
-       if (ret)
-               return ret;
-
-       provider = &qp->provider;
-       provider->dev = dev;
-       provider->set = msm8974_icc_set;
-       provider->aggregate = icc_std_aggregate;
-       provider->xlate = of_icc_xlate_onecell;
-       provider->data = data;
-       provider->get_bw = msm8974_get_bw;
-
-       icc_provider_init(provider);
-
-       for (i = 0; i < num_nodes; i++) {
-               size_t j;
-
-               node = icc_node_create(qnodes[i]->id);
-               if (IS_ERR(node)) {
-                       ret = PTR_ERR(node);
-                       goto err_remove_nodes;
-               }
-
-               node->name = qnodes[i]->name;
-               node->data = qnodes[i];
-               icc_node_add(node, provider);
-
-               dev_dbg(dev, "registered node %s\n", node->name);
-
-               /* populate links */
-               for (j = 0; j < qnodes[i]->num_links; j++)
-                       icc_link_create(node, qnodes[i]->links[j]);
-
-               data->nodes[i] = node;
-       }
-
-       ret = icc_provider_register(provider);
-       if (ret)
-               goto err_remove_nodes;
-
-       platform_set_drvdata(pdev, qp);
-
-       return 0;
-
-err_remove_nodes:
-       icc_nodes_remove(provider);
-       clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-
-       return ret;
-}
-
-static void msm8974_icc_remove(struct platform_device *pdev)
-{
-       struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
-
-       icc_provider_deregister(&qp->provider);
-       icc_nodes_remove(&qp->provider);
-       clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-}
-
 static const struct of_device_id msm8974_noc_of_match[] = {
        { .compatible = "qcom,msm8974-bimc", .data = &msm8974_bimc},
        { .compatible = "qcom,msm8974-cnoc", .data = &msm8974_cnoc},
@@ -758,8 +540,8 @@ static const struct of_device_id msm8974_noc_of_match[] = {
 MODULE_DEVICE_TABLE(of, msm8974_noc_of_match);
 
 static struct platform_driver msm8974_noc_driver = {
-       .probe = msm8974_icc_probe,
-       .remove = msm8974_icc_remove,
+       .probe = qnoc_probe,
+       .remove = qnoc_remove,
        .driver = {
                .name = "qnoc-msm8974",
                .of_match_table = msm8974_noc_of_match,