From 344b3605571de9d71699599ae238e91f3d1b05a2 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Mon, 19 Apr 2021 16:25:37 +0530 Subject: [PATCH] interconnect: qcom: Enable real interconnect provider for Monaco Introduce Qualcomm Monaco specific real provider driver using the interconnect framework. Also add sync_state for interconenct provider driver. Change-Id: I6963398294d8e7f427e878849d7d3635b4c58fc7 Signed-off-by: Odelu Kukatla --- drivers/interconnect/qcom/Kconfig | 3 + drivers/interconnect/qcom/monaco.c | 115 +++++++++++++++++++++++++---- 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index e3833669a1c1..5741ac1c00c7 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -20,6 +20,9 @@ config INTERCONNECT_QCOM_HOLI config INTERCONNECT_QCOM_MONACO tristate "MONACO interconnect driver" depends on INTERCONNECT_QCOM + depends on MSM_RPM_SMD + select INTERCONNECT_QCOM_RPM + select INTERCONNECT_QCOM_QOS help This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip on monaco-based platforms. The interconnect provider collects and diff --git a/drivers/interconnect/qcom/monaco.c b/drivers/interconnect/qcom/monaco.c index b95e15d2a658..f839bc69cef4 100644 --- a/drivers/interconnect/qcom/monaco.c +++ b/drivers/interconnect/qcom/monaco.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * */ @@ -23,6 +23,11 @@ #include "qnoc-qos.h" #include "rpm-ids.h" +static LIST_HEAD(qnoc_probe_list); +static DEFINE_MUTEX(probe_list_lock); + +static int probe_count; + static const struct clk_bulk_data bus_clocks[] = { { .id = "bus" }, { .id = "bus_a" }, @@ -983,6 +988,7 @@ static struct qcom_icc_node qxs_snoc_bimc = { .mas_rpm_id = -1, .slv_rpm_id = ICBID_SLAVE_SNOC_BIMC, .num_links = 1, + .links = { SNOC_BIMC_MAS }, }; static struct qcom_icc_node srvc_snoc = { @@ -1154,19 +1160,28 @@ static struct qcom_icc_desc monaco_sys_noc = { .num_nodes = ARRAY_SIZE(sys_noc_nodes), }; -static void qcom_icc_stub_pre_aggregate(struct icc_node *node) -{ -} +static const struct regmap_config icc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, +}; -static int qcom_icc_stub_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, - u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +static struct regmap * +qcom_icc_map(struct platform_device *pdev, const struct qcom_icc_desc *desc) { - return 0; -} + void __iomem *base; + struct resource *res; + struct device *dev = &pdev->dev; -static int qcom_icc_stub_set(struct icc_node *src, struct icc_node *dst) -{ - return 0; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return NULL; + + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return ERR_CAST(base); + + return devm_regmap_init_mmio(dev, base, &icc_regmap_config); } static int qnoc_probe(struct platform_device *pdev) @@ -1197,11 +1212,25 @@ static int qnoc_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + qp->bus_clks = devm_kmemdup(dev, bus_clocks, sizeof(bus_clocks), + GFP_KERNEL); + if (!qp->bus_clks) + return -ENOMEM; + + qp->num_clks = ARRAY_SIZE(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 = qcom_icc_stub_set; - provider->pre_aggregate = qcom_icc_stub_pre_aggregate; - provider->aggregate = qcom_icc_stub_aggregate; + provider->set = qcom_icc_rpm_set; + provider->pre_aggregate = qcom_icc_rpm_pre_aggregate; + provider->aggregate = qcom_icc_rpm_aggregate; provider->xlate = of_icc_xlate_onecell; INIT_LIST_HEAD(&provider->nodes); provider->data = data; @@ -1214,9 +1243,14 @@ static int qnoc_probe(struct platform_device *pdev) &qp->util_factor)) qp->util_factor = DEFAULT_UTIL_FACTOR; + qp->regmap = qcom_icc_map(pdev, desc); + if (IS_ERR(qp->regmap)) + return PTR_ERR(qp->regmap); + ret = icc_provider_add(provider); if (ret) { dev_err(dev, "error adding interconnect provider: %d\n", ret); + clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); return ret; } @@ -1226,6 +1260,8 @@ static int qnoc_probe(struct platform_device *pdev) if (!qnodes[i]) continue; + qnodes[i]->regmap = dev_get_regmap(qp->dev, NULL); + node = icc_node_create(qnodes[i]->id); if (IS_ERR(node)) { ret = PTR_ERR(node); @@ -1245,7 +1281,11 @@ static int qnoc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, qp); - dev_info(dev, "Registered monaco ICC\n"); + dev_info(dev, "Registered Monaco ICC\n"); + + mutex_lock(&probe_list_lock); + list_add_tail(&qp->probe_list, &qnoc_probe_list); + mutex_unlock(&probe_list_lock); return 0; err: @@ -1254,6 +1294,7 @@ err: icc_node_destroy(node->id); } + clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); icc_provider_del(provider); return ret; } @@ -1269,6 +1310,8 @@ static int qnoc_remove(struct platform_device *pdev) icc_node_destroy(n->id); } + clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); + return icc_provider_del(provider); } @@ -1289,12 +1332,54 @@ static const struct of_device_id qnoc_of_match[] = { }; MODULE_DEVICE_TABLE(of, qnoc_of_match); +static void qnoc_sync_state(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + int ret = 0, i; + + mutex_lock(&probe_list_lock); + probe_count++; + + if (probe_count < ARRAY_SIZE(qnoc_of_match) - 1) { + mutex_unlock(&probe_list_lock); + return; + } + + list_for_each_entry(qp, &qnoc_probe_list, probe_list) { + qp->init = false; + + if (!qp->keepalive) + continue; + + for (i = 0; i < RPM_NUM_CXT; i++) { + if (i == RPM_ACTIVE_CXT) { + if (qp->bus_clk_cur_rate[i] == 0) + ret = clk_set_rate(qp->bus_clks[i].clk, + RPM_CLK_MIN_LEVEL); + else + ret = clk_set_rate(qp->bus_clks[i].clk, + qp->bus_clk_cur_rate[i]); + + if (ret) + pr_err("%s clk_set_rate error: %d\n", + qp->bus_clks[i].id, ret); + } + } + } + + mutex_unlock(&probe_list_lock); + + pr_err("Monaco ICC Sync State done\n"); +} + static struct platform_driver qnoc_driver = { .probe = qnoc_probe, .remove = qnoc_remove, .driver = { .name = "qnoc-monaco", .of_match_table = qnoc_of_match, + .sync_state = qnoc_sync_state, }, };