From patchwork Wed Mar 13 19:34:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 10851699 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C899F6C2 for ; Wed, 13 Mar 2019 19:34:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B04B429D2B for ; Wed, 13 Mar 2019 19:34:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A10CF29D31; Wed, 13 Mar 2019 19:34:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4924F28A15 for ; Wed, 13 Mar 2019 19:34:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727481AbfCMTd5 (ORCPT ); Wed, 13 Mar 2019 15:33:57 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:45541 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727531AbfCMTdt (ORCPT ); Wed, 13 Mar 2019 15:33:49 -0400 Received: by mail-wr1-f68.google.com with SMTP id h99so3284352wrh.12 for ; Wed, 13 Mar 2019 12:33:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=e3q2Y8Ae5Q5aVEznQVZGdY0m0MoL10v1q/utHM3EnH4=; b=BkuOrRsgdNXQFNV+9veLeqf5YHkdAOMwLg3F+QcnTAoAKjOK8Jcntzg0iS7Vj7Im9+ UWRnFFn6ihMl02P+XwJwFrtkF2ze5LXZyJejpVO6CRu9uJhaj3o0E+EPUM8Kmmehto16 HdIkXVqgpzdEU+vZgAx7X45Dfs8F7aQ/DgoO0+/6hY/O4n21EWofls+kJJ2HsLp5tcI4 coCa8SJyrUWi46hkklr+hTdaspmKgYm3rTZKgqLc75NHS/gJv36QVU23nA56hJyZQX/N 5HJRxgcYcrH+jN6MR9IWikQEpNoKti9MpFT7OQANyjPpdgPM2w7ib3CxSyf3HxpRfzb+ jSgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=e3q2Y8Ae5Q5aVEznQVZGdY0m0MoL10v1q/utHM3EnH4=; b=PbWKTKbjq/6tJHKgHTDRK62KFnBqU9QNDTdTJMIvV2qJl60M6V3rgxyL7Ld2M2Tyxq L2eIzkd/ebw+tT7c8hSK1CDpE5O3L5Q7UwqXOHSf+lyDCjib3PTT9DS5/ibKtPeEzYXN s6Jf6upIModWEpRuuYU2RQBrQvnst+NJKdRWRoA76Xrwh8ct9J+iN7+XCOt8g4NldDX4 UUDJYxT0C1nVTErq927qeyHO18wde3AuiZ6rzrr7aiHIjAYVg8Gy+m2qH0TMWRpbToiM FgfatemrZcKfdjOjRtjvbGa6gyIUGotdAe+5C/SjJgISl/Oi4qoZSMXm65OLgRC2v3i5 qc2g== X-Gm-Message-State: APjAAAWVAEk4wb4veoBuY/oGBE+kVFGnTfYFPCD2U3K+gCvEHhDntHJw 5aD1666J3lKPq/Pp4/0g33kYvYuYcnM= X-Google-Smtp-Source: APXvYqwjGo0j1Agl0Z7RcINl3l2dnjeam31Oium87w+TUqOqFHJVngwy4Z/1TML9GtI9rSUiH8wncg== X-Received: by 2002:adf:9cc3:: with SMTP id h3mr27658602wre.47.1552505625104; Wed, 13 Mar 2019 12:33:45 -0700 (PDT) Received: from localhost.localdomain (205.66.21.93.rev.sfr.net. [93.21.66.205]) by smtp.gmail.com with ESMTPSA id z198sm3017497wmc.10.2019.03.13.12.33.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 Mar 2019 12:33:44 -0700 (PDT) From: Alexandre Bailon To: linux-pm@vger.kernel.org, georgi.djakov@linaro.org Cc: mturquette@baylibre.com, ptitiano@baylibre.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, zening.wang@nxp.com, aisheng.dong@nxp.com, khilman@baylibre.com, ccaione@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 1/3] drivers: interconnect: Add a driver for i.MX SoC Date: Wed, 13 Mar 2019 20:34:06 +0100 Message-Id: <20190313193408.23740-2-abailon@baylibre.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190313193408.23740-1-abailon@baylibre.com> References: <20190313193408.23740-1-abailon@baylibre.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds support of i.MX SoC to interconnect framework. This is based on busfreq, from NXP's tree. This is is generic enough to be used to add support of interconnect framework to any i.MX SoC, and, even, this could used for some other SoC. Thanks to interconnect framework, devices' driver request for bandwidth which is use by busfreq to determine a performance level, and then scale the frequency. Busfreq platform drivers just have to registers interconnect nodes, and OPPs. Signed-off-by: Alexandre Bailon --- drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 13 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/busfreq.c | 570 +++++++++++++++++++++++++++++ drivers/interconnect/imx/busfreq.h | 123 +++++++ 6 files changed, 709 insertions(+) create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/busfreq.c create mode 100644 drivers/interconnect/imx/busfreq.h diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig index 07a8276fa35a..99955906bea8 100644 --- a/drivers/interconnect/Kconfig +++ b/drivers/interconnect/Kconfig @@ -11,5 +11,6 @@ menuconfig INTERCONNECT if INTERCONNECT source "drivers/interconnect/qcom/Kconfig" +source "drivers/interconnect/imx/Kconfig" endif diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index 28f2ab0824d5..20a13b7eb37f 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -4,3 +4,4 @@ icc-core-objs := core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ +obj-$(CONFIG_INTERCONNECT_IMX) += imx/ diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig new file mode 100644 index 000000000000..afd7b71bbd82 --- /dev/null +++ b/drivers/interconnect/imx/Kconfig @@ -0,0 +1,13 @@ +config INTERCONNECT_IMX + bool "i.MX interconnect drivers" + depends on ARCH_MXC || ARCH_MXC_ARM64 || COMPILE_TEST + help + Support for i.MX interconnect hardware. + +config BUSFREQ + bool "busfreq interconnect driver" + depends on INTERCONNECT_IMX + help + A generic interconnect driver that could be used for any i.MX. + This provides a way to register master and slave and some opp + to use when one or more master are in use. diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile new file mode 100644 index 000000000000..fea647183815 --- /dev/null +++ b/drivers/interconnect/imx/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_BUSFREQ) += busfreq.o diff --git a/drivers/interconnect/imx/busfreq.c b/drivers/interconnect/imx/busfreq.c new file mode 100644 index 000000000000..af461f788468 --- /dev/null +++ b/drivers/interconnect/imx/busfreq.c @@ -0,0 +1,570 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Interconnect framework driver for i.MX SoC + * + * Copyright (c) 2019, BayLibre + * Author: Alexandre Bailon + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "busfreq.h" + +/* + * struct busfreq_opp_node - Describe the minimum bandwidth required by a node + * to enable the opp + * @icc_node: icc_node to test + * @min_avg_bw: minimum average bandwidth in kbps required to enable opp + * @min_peak_bw: minimum peak bandwidth in kbps required to enable opp + */ +struct busfreq_opp_node { + struct icc_node *icc_node; + u32 min_avg_bw; + u32 min_peak_bw; +}; + +/* + * struct busfreq_opp - Describe an opp + * This is used to configure multiple clock at once with the respect of + * hardware and performance requirements. + * @clks_count: number of clocks to configure + * @clks: array of clock + * @rates: array of rate, to apply for each clock when the opp is enabled + * @perf_level: Used to select the opp that would allow the lowest power + * consumption when two or more opp satisfies the performances + * requirements + * @node: entry in list of opp + * @nodes_count: number of opp node + * @nodes: array of opp node, to check node by node if opp satisfies the + * the required performances + */ +struct busfreq_opp { + int clks_count; + struct clk **clks; + u64 *rates; + u32 perf_level; + + struct list_head node; + + int nodes_count; + struct busfreq_opp_node *nodes; +}; + +/* + * struct busfreq_icc_desc - Hold data required to control the interconnects + * @dev: device pointer for the overall interconnect + * @opps: list of opp + * @default_opp: the opp opp to use when the system is in special states + * (boot, suspend, resume, shutdown) + * @current_opp: the opp currently in use + * @opp_locked: prevent opp to change while this is set + * @pm_notifier: used to set the default opp before suspend and + * and select the best one after resume + * @pm_notifier: used to set the default opp before to reboot + */ +struct busfreq_icc_desc { + struct device *dev; + + struct list_head opps; + struct busfreq_opp *default_opp; + struct busfreq_opp *current_opp; + bool opp_locked; + + struct notifier_block pm_notifier; + struct notifier_block reboot_notifier; + + struct mutex mutex; +}; + +static int busfreq_icc_aggregate(struct icc_node *node, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + *agg_avg += avg_bw; + *agg_peak = max(*agg_peak, peak_bw); + + return 0; +} + +static int busfreq_set_opp_no_lock(struct busfreq_icc_desc *desc, + struct busfreq_opp *requested_opp) +{ + int ret; + int i; + + if (!requested_opp && !desc->default_opp) + return -EINVAL; + + if (!requested_opp) + requested_opp = desc->default_opp; + + if (desc->current_opp == requested_opp) + return 0; + + if (desc->opp_locked) + return -EBUSY; + + for (i = 0; i < requested_opp->clks_count; i++) { + ret = clk_set_rate(requested_opp->clks[i], + requested_opp->rates[i]); + if (ret) + goto err; + } + desc->current_opp = requested_opp; + + return 0; + +err: + dev_err(desc->dev, "Failed to set opp\n"); + for (; i >= 0; i--) + clk_set_rate(desc->current_opp->clks[i], + desc->current_opp->rates[i]); + return ret; +} + +static int busfreq_set_opp(struct busfreq_icc_desc *desc, + struct busfreq_opp *requested_opp) +{ + int ret; + + mutex_lock(&desc->mutex); + ret = busfreq_set_opp_no_lock(desc, requested_opp); + mutex_unlock(&desc->mutex); + + return ret; +} + +static int busfreq_opp_bw_gt(struct busfreq_opp_node *opp_node, + u32 avg_bw, u32 peak_bw) +{ + if (!opp_node) + return 0; + if (opp_node->min_avg_bw == BUSFREQ_UNDEFINED_BW) { + if (avg_bw) + return 2; + else + return 1; + } + if (opp_node->min_peak_bw == BUSFREQ_UNDEFINED_BW) { + if (peak_bw) + return 2; + else + return 1; + } + if (avg_bw >= opp_node->min_avg_bw) + return 1; + if (peak_bw >= opp_node->min_peak_bw) + return 1; + return 0; +} + +static struct busfreq_opp *busfreq_cmp_bw_opp(struct busfreq_icc_desc *desc, + struct busfreq_opp *opp1, + struct busfreq_opp *opp2) +{ + int i; + int opp1_valid; + int opp2_valid; + int opp1_count = 0; + int opp2_count = 0; + + if (!opp1 && !opp2) + return desc->current_opp; + + if (!opp1) + return opp2; + + if (!opp2) + return opp1; + + if (opp1 == opp2) + return opp1; + + for (i = 0; i < opp1->nodes_count; i++) { + struct busfreq_opp_node *opp_node1, *opp_node2; + struct icc_node *icc_node; + u32 avg_bw; + u32 peak_bw; + + opp_node1 = &opp1->nodes[i]; + opp_node2 = &opp2->nodes[i]; + icc_node = opp_node1->icc_node; + avg_bw = icc_node->avg_bw; + peak_bw = icc_node->peak_bw; + + opp1_valid = busfreq_opp_bw_gt(opp_node1, avg_bw, peak_bw); + opp2_valid = busfreq_opp_bw_gt(opp_node2, avg_bw, peak_bw); + + if (opp1_valid == opp2_valid && opp1_valid == 1) { + if (opp_node1->min_avg_bw > opp_node2->min_avg_bw && + opp_node1->min_avg_bw != BUSFREQ_UNDEFINED_BW) + opp1_valid++; + if (opp_node1->min_avg_bw < opp_node2->min_avg_bw && + opp_node2->min_avg_bw != BUSFREQ_UNDEFINED_BW) + opp2_valid++; + } + + opp1_count += opp1_valid; + opp2_count += opp2_valid; + } + + if (opp1_count > opp2_count) + return opp1; + if (opp1_count < opp2_count) + return opp2; + return opp1->perf_level >= opp2->perf_level ? opp2 : opp1; +} + +static int busfreq_set_best_opp(struct busfreq_icc_desc *desc) +{ + struct busfreq_opp *opp, *best_opp = desc->current_opp; + + list_for_each_entry(opp, &desc->opps, node) + best_opp = busfreq_cmp_bw_opp(desc, opp, best_opp); + return busfreq_set_opp(desc, best_opp); +} + +static int busfreq_set_locked_opp(struct busfreq_icc_desc *desc, + struct busfreq_opp *requested_opp) +{ + int ret; + + mutex_lock(&desc->mutex); + ret = busfreq_set_opp_no_lock(desc, requested_opp); + if (ret) + goto err; + desc->opp_locked = true; +err: + mutex_unlock(&desc->mutex); + + return ret; +} + +static int busfreq_unlock_opp(struct busfreq_icc_desc *desc) +{ + mutex_lock(&desc->mutex); + desc->opp_locked = false; + mutex_unlock(&desc->mutex); + + return busfreq_set_best_opp(desc); +} + +static int busfreq_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct busfreq_icc_desc *desc = src->provider->data; + + if (!dst->num_links) + return busfreq_set_best_opp(desc); + + return 0; +} + +static int busfreq_pm_notify(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct busfreq_icc_desc *desc; + + desc = container_of(nb, struct busfreq_icc_desc, pm_notifier); + if (event == PM_SUSPEND_PREPARE) + busfreq_set_locked_opp(desc, desc->default_opp); + else if (event == PM_POST_SUSPEND) + busfreq_unlock_opp(desc); + + return NOTIFY_OK; +} + +static int busfreq_reboot_notify(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct busfreq_icc_desc *desc; + + desc = container_of(nb, struct busfreq_icc_desc, reboot_notifier); + busfreq_set_locked_opp(desc, desc->default_opp); + + return NOTIFY_OK; +} + +static struct icc_node *busfreq_icc_node_add(struct icc_provider *provider, + int id, const char *name) +{ + struct busfreq_icc_desc *desc = provider->data; + struct device *dev = desc->dev; + struct icc_node *icc_node; + + icc_node = icc_node_create(id); + if (IS_ERR(icc_node)) { + dev_err(dev, "Failed to create node %d\n", id); + return icc_node; + } + + if (icc_node->data) + return icc_node; + + icc_node->name = name; + icc_node->data = &icc_node; + icc_node_add(icc_node, provider); + + return icc_node; +} + +static struct icc_node *busfreq_icc_node_get(struct icc_provider *provider, + int id) +{ + return busfreq_icc_node_add(provider, id, NULL); +} + +static void busfreq_unregister_nodes(struct icc_provider *provider) +{ + struct icc_node *icc_node, *tmp; + + list_for_each_entry_safe(icc_node, tmp, &provider->nodes, node_list) + icc_node_destroy(icc_node->id); +} + +static int busfreq_register_nodes(struct icc_provider *provider, + struct busfreq_icc_node *busfreq_nodes, + int count) +{ + int ret; + int i; + + for (i = 0; i < count; i++) { + struct icc_node *icc_node; + size_t j; + + icc_node = busfreq_icc_node_add(provider, + busfreq_nodes[i].id, + busfreq_nodes[i].name); + if (IS_ERR(icc_node)) { + ret = PTR_ERR(icc_node); + goto err; + } + + for (j = 0; j < busfreq_nodes[i].num_links; j++) + icc_link_create(icc_node, busfreq_nodes[i].links[j]); + } + + return 0; + +err: + busfreq_unregister_nodes(provider); + + return ret; +} + +static struct busfreq_opp *busfreq_opp_alloc(struct icc_provider *provider, + int count) +{ + struct busfreq_icc_desc *desc = provider->data; + struct device *dev = desc->dev; + struct busfreq_opp *opp; + struct icc_node *icc_node; + + opp = devm_kzalloc(dev, sizeof(*opp), GFP_KERNEL); + if (!opp) + return ERR_PTR(-ENOMEM); + + opp->clks_count = count; + opp->clks = devm_kzalloc(dev, sizeof(struct clk *) * count, GFP_KERNEL); + if (!opp->clks) + return ERR_PTR(-ENOMEM); + + opp->rates = devm_kzalloc(dev, sizeof(u64) * count, GFP_KERNEL); + if (!opp->rates) + return ERR_PTR(-ENOMEM); + + count = 0; + list_for_each_entry(icc_node, &provider->nodes, node_list) + count++; + + opp->nodes = devm_kzalloc(dev, sizeof(*opp->nodes) * count, GFP_KERNEL); + if (!opp->nodes) + return ERR_PTR(-ENOMEM); + opp->nodes_count = count; + + return opp; +} + +static int busfreq_init_opp(struct icc_provider *provider, + struct busfreq_opp *opp, + struct busfreq_plat_opp *plat_opp) +{ + struct busfreq_icc_desc *desc = provider->data; + struct device *dev = desc->dev; + struct busfreq_opp_node *node; + struct icc_node *icc_node; + int i, j; + + opp->perf_level = 0; + for (i = 0; i < opp->clks_count; i++) { + opp->clks[i] = devm_clk_get(dev, plat_opp->clks[i].name); + if (IS_ERR(opp->clks[i])) { + dev_err(dev, "Failed to get clock %s\n", + plat_opp->clks[i].name); + return PTR_ERR(opp->clks[i]); + } + opp->rates[i] = plat_opp->clks[i].rate; + opp->perf_level += opp->rates[i] >> 10; + } + + i = 0; + list_for_each_entry(icc_node, &provider->nodes, node_list) { + node = &opp->nodes[i++]; + node->icc_node = icc_node; + } + + for (i = 0; i < plat_opp->nodes_count; i++) { + icc_node = busfreq_icc_node_get(provider, + plat_opp->nodes[i].id); + if (IS_ERR_OR_NULL(icc_node)) + return -EINVAL; + + for (j = 0, node = &opp->nodes[j]; j < opp->nodes_count; + j++, node = &opp->nodes[j]) { + if (node->icc_node == icc_node) { + node->min_avg_bw = BUSFREQ_UNDEFINED_BW; + node->min_peak_bw = BUSFREQ_UNDEFINED_BW; + } + } + } + + INIT_LIST_HEAD(&opp->node); + + return 0; +} + +static int busfreq_register_opps(struct device *dev, + struct icc_provider *provider, + struct busfreq_plat_opp *busfreq_opps, + int count) +{ + struct busfreq_icc_desc *desc = provider->data; + struct busfreq_opp *opp; + int ret; + int i; + + for (i = 0; i < count; i++) { + opp = busfreq_opp_alloc(provider, busfreq_opps[i].clks_count); + if (IS_ERR(opp)) + return PTR_ERR(opp); + + ret = busfreq_init_opp(provider, opp, &busfreq_opps[i]); + if (ret) + return ret; + + if (busfreq_opps[i].default_opp) + desc->default_opp = opp; + + list_add(&opp->node, &desc->opps); + } + + return 0; +} + +static void busfreq_unregister_opps(struct icc_provider *provider) +{ + struct busfreq_icc_desc *desc = provider->data; + struct device *dev = desc->dev; + struct busfreq_opp *opp, *tmp_opp; + + list_for_each_entry_safe(opp, tmp_opp, &desc->opps, node) { + list_del(&opp->node); + devm_kfree(dev, opp->nodes); + devm_kfree(dev, opp->clks); + devm_kfree(dev, opp->rates); + devm_kfree(dev, opp); + } +} + +int busfreq_register(struct platform_device *pdev, + struct busfreq_icc_node *busfreq_nodes, int nodes_count, + struct busfreq_plat_opp *busfreq_opps, int opps_count) +{ + struct device *dev = &pdev->dev; + struct busfreq_icc_desc *desc; + struct icc_provider *provider; + int ret; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + desc->dev = dev; + mutex_init(&desc->mutex); + INIT_LIST_HEAD(&desc->opps); + + provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL); + if (!provider) + return -ENOMEM; + provider->set = busfreq_icc_set; + provider->aggregate = busfreq_icc_aggregate; + provider->data = desc; + platform_set_drvdata(pdev, provider); + + ret = icc_provider_add(provider); + if (ret) { + dev_err(dev, "error adding interconnect provider\n"); + return ret; + } + + ret = busfreq_register_nodes(provider, busfreq_nodes, nodes_count); + if (ret) { + dev_err(dev, "error adding interconnect nodes\n"); + goto provider_del; + } + + ret = busfreq_register_opps(dev, provider, busfreq_opps, opps_count); + if (ret) { + dev_err(dev, "error adding busfreq opp\n"); + goto unregister_nodes; + } + + ret = busfreq_set_opp(desc, desc->default_opp); + if (ret) + goto unregister_opps; + + desc->pm_notifier.notifier_call = busfreq_pm_notify; + register_pm_notifier(&desc->pm_notifier); + + desc->reboot_notifier.notifier_call = busfreq_reboot_notify; + register_reboot_notifier(&desc->reboot_notifier); + + return 0; + +unregister_opps: + busfreq_unregister_opps(provider); +unregister_nodes: + busfreq_unregister_nodes(provider); +provider_del: + icc_provider_del(provider); + return ret; +} +EXPORT_SYMBOL_GPL(busfreq_register); + +int busfreq_unregister(struct platform_device *pdev) +{ + struct icc_provider *provider = platform_get_drvdata(pdev); + struct busfreq_icc_desc *desc = provider->data; + int ret; + + unregister_reboot_notifier(&desc->reboot_notifier); + unregister_pm_notifier(&desc->pm_notifier); + + ret = busfreq_set_opp(desc, desc->default_opp); + if (ret) + return ret; + + icc_provider_del(provider); + + busfreq_unregister_opps(provider); + busfreq_unregister_nodes(provider); + devm_kfree(&pdev->dev, desc); + devm_kfree(&pdev->dev, provider); + + return 0; +} +EXPORT_SYMBOL_GPL(busfreq_unregister); diff --git a/drivers/interconnect/imx/busfreq.h b/drivers/interconnect/imx/busfreq.h new file mode 100644 index 000000000000..a60481f10500 --- /dev/null +++ b/drivers/interconnect/imx/busfreq.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Interconnect framework driver for i.MX SoC + * + * Copyright (c) 2019, BayLibre + * Author: Alexandre Bailon + */ +#ifndef __BUSFREQ_H +#define __BUSFREQ_H + +#include + +#define BUSFREQ_MAX_LINKS 32 +#define BUSFREQ_UNDEFINED_BW 0xffffffff + +/* + * struct busfreq_icc_node - Describe an interconnect node + * @name: name of the node + * @id: an unique id to identify the node + * @links: an array of slaves' node id + * @num_links: number of id defined in links + */ +struct busfreq_icc_node { + char *name; + u16 id; + u16 links[BUSFREQ_MAX_LINKS]; + u16 num_links; +}; + +/* + * struct busfreq_opp_clk - Clock name and rate to set for an opp + * @name: name of clock + * @rate: the rate to set when the opp is enabled + */ +struct busfreq_opp_clk { + char *name; + unsigned long rate; +}; + +/* + * struct busfreq_opp_bw - Describe a condition to meet to enable an opp + * @id: id of the node to test + * @avg_bw: minimum average bandwidth required to enable the opp, or + * ignored if set to BUSFREQ_UNDEFINED_BW + * @peak_bw: minimum peak bandwidth required to enable the opp, or + * ignored if set to BUSFREQ_UNDEFINED_BW + */ +struct busfreq_opp_bw { + u16 id; + u32 avg_bw; + u32 peak_bw; +}; + +/* + * struct busfreq_plat_opp - Describe an opp to register in busfreq + * @clks: array of clocks to configure when the opp is enable + * @clks_count: number of clocks + * @nodes: array of opp nodes (condition to meet for each node to enable opp) + * @nodes_count: number of nodes + * @default_opp: use this opp as default opp if true + */ +struct busfreq_plat_opp { + struct busfreq_opp_clk *clks; + int clks_count; + struct busfreq_opp_bw *nodes; + int nodes_count; + bool default_opp; +}; + +#define DEFINE_BUS_INTERCONNECT(_name, _id, _numlinks, ...) \ + { \ + .id = _id, \ + .name = _name, \ + .num_links = _numlinks, \ + .links = { __VA_ARGS__ }, \ + } + +#define DEFINE_BUS_MASTER(_name, _id, _dest_id) \ + DEFINE_BUS_INTERCONNECT(_name, _id, 1, _dest_id) + +#define DEFINE_BUS_SLAVE(_name, _id) \ + DEFINE_BUS_INTERCONNECT(_name, _id, 0) + +#define DEFINE_OPP_CLOCK(_name, _rate) \ + { \ + .name = _name, \ + .rate = _rate, \ + } + +#define DEFINE_OPP_BW(_id, _avg, _peak) \ + { \ + .id = _id, \ + .avg_bw = _avg, \ + .peak_bw = _peak, \ + } + +#define DEFINE_OPP_NODE(_id) \ + DEFINE_OPP_BW(_id, BUSFREQ_UNDEFINED_BW, BUSFREQ_UNDEFINED_BW) + +#define DEFINE_OPP(_clks, _nodes, _default) \ + { \ + .clks = _clks, \ + .clks_count = ARRAY_SIZE(_clks), \ + .nodes = _nodes, \ + .nodes_count = ARRAY_SIZE(_nodes), \ + .default_opp = _default, \ + } + +#define DEFINE_OPP_NO_NODES(_clks, _default) \ + { \ + .clks = _clks, \ + .clks_count = ARRAY_SIZE(_clks), \ + .nodes = NULL, \ + .nodes_count = 0, \ + .default_opp = _default, \ + } + +int busfreq_register(struct platform_device *pdev, + struct busfreq_icc_node *busfreq_nodes, int nodes_count, + struct busfreq_plat_opp *busfreq_opps, int opps_count); +int busfreq_unregister(struct platform_device *pdev); + +#endif /* __BUSFREQ_H */ From patchwork Wed Mar 13 19:34:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 10851693 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EED586C2 for ; Wed, 13 Mar 2019 19:33:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DB14C29BCB for ; Wed, 13 Mar 2019 19:33:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CEB5D29C4E; Wed, 13 Mar 2019 19:33:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ABF3B29BCB for ; Wed, 13 Mar 2019 19:33:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727707AbfCMTdu (ORCPT ); Wed, 13 Mar 2019 15:33:50 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:35715 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727560AbfCMTdt (ORCPT ); Wed, 13 Mar 2019 15:33:49 -0400 Received: by mail-wr1-f65.google.com with SMTP id t18so3317872wrx.2 for ; Wed, 13 Mar 2019 12:33:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9WBXmNn4StehscAZZnU0MKJI6NK9pgoT630krc3+Cgo=; b=uhcsbeBKnXhIbnOvppqkS8/0labsp64fSUsjAwd7QoW11Ivv+oDnXaIlKdBiFxf5k8 15FhTnv68UInDqeQ3DtFvluM6SqgK5FSVrFx4ryqFwdBJQa//9E6wwjStgsDtO6Ty63a os/BoqWc8fh7IcP8l3p82xTBYPOJAUrRUIOZtaMelx/J7N1F7frH8RGJar5VJb5ezG/d xJrbNb61i/T6bRSu8If7dFoen8JjFhkKMSI0MAF+GZJj3XDZERUPlJ5pGuGdTlBILdzU 3F/1cu8nJGyTfy04WlP0bxKk4GZV94WdTuaA7LGmw1JWSgkB7s88Z6d0i8Yd35IyuD3T wf5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9WBXmNn4StehscAZZnU0MKJI6NK9pgoT630krc3+Cgo=; b=BKrgcntsBqI2W+4e072xXj7Xc8EUl+j8IOLrnJMZ2hOSgLH+duXZ7md3tsq3Zt65J8 IRgWiGiC7L98Ebi550wQbCe+/cneOeMPrNZ3167isqwT5xdHzEghJmST91g50w8k1w0D aPFKkU/g1dYc0n7nsfwQenHK+UYtbNSLvfetpxUP06QyAXWrQ/bcubQBXHHYl7ERxHMD JdTNaSIliBJrMT5IEUmdaKHYq5BJOefuFpQI7krmYEWq32N5QSFTKy8ru+h4VXxLQdU2 Zl3Mzezzl/vHEOX51ZJ92H6rMpvRMUjo44WddK8j+2hlGyqinMYHA+t2jlWbcH/B/CNg j0SA== X-Gm-Message-State: APjAAAVRMWaA1epZuZJ9aAjR+CnLbE4lRlcOLBj9KzR4qGofW1cK61PT ct6KJbOa8KRss6cVwqiK6ZKmTL1gd30= X-Google-Smtp-Source: APXvYqxxzjnP/Lp48jWJ/5p35pfgJXrELFTsCqpMsATR/Jg6stAepm24Xs6LM+WJ9eZbLF8o/T5mIw== X-Received: by 2002:a5d:4583:: with SMTP id p3mr14261835wrq.114.1552505626654; Wed, 13 Mar 2019 12:33:46 -0700 (PDT) Received: from localhost.localdomain (205.66.21.93.rev.sfr.net. [93.21.66.205]) by smtp.gmail.com with ESMTPSA id z198sm3017497wmc.10.2019.03.13.12.33.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 Mar 2019 12:33:45 -0700 (PDT) From: Alexandre Bailon To: linux-pm@vger.kernel.org, georgi.djakov@linaro.org Cc: mturquette@baylibre.com, ptitiano@baylibre.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, zening.wang@nxp.com, aisheng.dong@nxp.com, khilman@baylibre.com, ccaione@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 2/3] drivers: interconnect: imx: Add support of i.MX8MM Date: Wed, 13 Mar 2019 20:34:07 +0100 Message-Id: <20190313193408.23740-3-abailon@baylibre.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190313193408.23740-1-abailon@baylibre.com> References: <20190313193408.23740-1-abailon@baylibre.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds a platform driver for the i.MX8MM SoC. Signed-off-by: Alexandre Bailon --- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/busfreq-imx8mm.c | 132 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mm.h | 37 ++++++ 4 files changed, 174 insertions(+) create mode 100644 drivers/interconnect/imx/busfreq-imx8mm.c create mode 100644 include/dt-bindings/interconnect/imx8mm.h diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig index afd7b71bbd82..b569d40e5ca0 100644 --- a/drivers/interconnect/imx/Kconfig +++ b/drivers/interconnect/imx/Kconfig @@ -11,3 +11,7 @@ config BUSFREQ A generic interconnect driver that could be used for any i.MX. This provides a way to register master and slave and some opp to use when one or more master are in use. + +config BUSFREQ_IMX8MM + bool "i.MX8MM busfreq driver" + depends on BUSFREQ diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile index fea647183815..a92fea6e042d 100644 --- a/drivers/interconnect/imx/Makefile +++ b/drivers/interconnect/imx/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_BUSFREQ) += busfreq.o +obj-$(CONFIG_BUSFREQ_IMX8MM) += busfreq-imx8mm.o diff --git a/drivers/interconnect/imx/busfreq-imx8mm.c b/drivers/interconnect/imx/busfreq-imx8mm.c new file mode 100644 index 000000000000..c3b10a49dc29 --- /dev/null +++ b/drivers/interconnect/imx/busfreq-imx8mm.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Interconnect framework driver for i.MX SoC + * + * Copyright (c) 2019, BayLibre + * Author: Alexandre Bailon + */ + +#include +#include +#include +#include + +#include + +#include "busfreq.h" + +static struct busfreq_icc_node imx8mm_icc_nodes[] = { + /* NOC */ + DEFINE_BUS_MASTER("A53-0", IMX8MM_CPU_0, IMX8MM_NOC), + DEFINE_BUS_MASTER("A53-1", IMX8MM_CPU_1, IMX8MM_NOC), + DEFINE_BUS_MASTER("A53-2", IMX8MM_CPU_2, IMX8MM_NOC), + DEFINE_BUS_MASTER("A53-3", IMX8MM_CPU_3, IMX8MM_NOC), + DEFINE_BUS_MASTER("VPU H1", IMX8MM_VPU_H1, IMX8MM_NOC), + DEFINE_BUS_MASTER("VPU G1", IMX8MM_VPU_G1, IMX8MM_NOC), + DEFINE_BUS_MASTER("VPU G2", IMX8MM_VPU_G2, IMX8MM_NOC), + DEFINE_BUS_MASTER("MIPI", IMX8MM_MIPI, IMX8MM_NOC), + DEFINE_BUS_MASTER("USB-1", IMX8MM_USB_1, IMX8MM_NOC), + DEFINE_BUS_MASTER("USB-2", IMX8MM_USB_1, IMX8MM_NOC), + DEFINE_BUS_MASTER("GPU", IMX8MM_GPU, IMX8MM_NOC), + DEFINE_BUS_MASTER("PCIE", IMX8MM_PCIE, IMX8MM_NOC), + DEFINE_BUS_SLAVE("DRAM", IMX8MM_DRAM), + DEFINE_BUS_INTERCONNECT("NOC", IMX8MM_NOC, 1, IMX8MM_DRAM), + + /* PL301 */ + DEFINE_BUS_MASTER("SAI-1", IMX8MM_SAI1, IMX8MM_PL301), + DEFINE_BUS_MASTER("SAI-2", IMX8MM_SAI2, IMX8MM_PL301), + DEFINE_BUS_MASTER("SAI-3", IMX8MM_SAI3, IMX8MM_PL301), + DEFINE_BUS_MASTER("SAI-4", IMX8MM_SAI4, IMX8MM_PL301), + DEFINE_BUS_MASTER("SAI-5", IMX8MM_SAI5, IMX8MM_PL301), + DEFINE_BUS_MASTER("SAI-6", IMX8MM_SAI6, IMX8MM_PL301), + DEFINE_BUS_MASTER("SPDIF", IMX8MM_SPDIF, IMX8MM_PL301), + DEFINE_BUS_MASTER("FEC", IMX8MM_FEC, IMX8MM_PL301), + DEFINE_BUS_INTERCONNECT("PL301", IMX8MM_PL301, 1, IMX8MM_NOC), +}; + +static struct busfreq_opp_clk imx8mm_low_freq_clks[] = { + DEFINE_OPP_CLOCK("dram-alt", 100000000), + DEFINE_OPP_CLOCK("dram-apb", 40000000), + DEFINE_OPP_CLOCK("dram-core", 25000000), + DEFINE_OPP_CLOCK("noc", 150000000), + DEFINE_OPP_CLOCK("ahb", 22222222), + DEFINE_OPP_CLOCK("axi", 24000000), +}; + +static struct busfreq_opp_clk imx8mm_audio_freq_clks[] = { + DEFINE_OPP_CLOCK("dram-alt", 400000000), + DEFINE_OPP_CLOCK("dram-apb", 40000000), + DEFINE_OPP_CLOCK("dram-core", 100000000), + DEFINE_OPP_CLOCK("noc", 150000000), + DEFINE_OPP_CLOCK("ahb", 22222222), + DEFINE_OPP_CLOCK("axi", 24000000), +}; + +static struct busfreq_opp_bw imx8mm_audio_freq_nodes[] = { + DEFINE_OPP_NODE(IMX8MM_SAI1), + DEFINE_OPP_NODE(IMX8MM_SAI2), + DEFINE_OPP_NODE(IMX8MM_SAI3), + DEFINE_OPP_NODE(IMX8MM_SAI4), + DEFINE_OPP_NODE(IMX8MM_SAI5), + DEFINE_OPP_NODE(IMX8MM_SAI6), + DEFINE_OPP_NODE(IMX8MM_SPDIF), +}; + +static struct busfreq_opp_clk imx8mm_high_freq_clks[] = { + DEFINE_OPP_CLOCK("dram-apb", 800000000), + DEFINE_OPP_CLOCK("dram-core", 750000000), + DEFINE_OPP_CLOCK("noc", 750000000), + DEFINE_OPP_CLOCK("ahb", 133333333), + DEFINE_OPP_CLOCK("axi", 333000000), +}; + +static struct busfreq_opp_bw imx8mm_high_freq_nodes[] = { + DEFINE_OPP_NODE(IMX8MM_SAI1), + DEFINE_OPP_NODE(IMX8MM_SAI2), + DEFINE_OPP_NODE(IMX8MM_SAI3), + DEFINE_OPP_NODE(IMX8MM_SAI4), + DEFINE_OPP_NODE(IMX8MM_SAI5), + DEFINE_OPP_NODE(IMX8MM_SAI6), + DEFINE_OPP_NODE(IMX8MM_SPDIF), + DEFINE_OPP_NODE(IMX8MM_MIPI), +}; + +static struct busfreq_plat_opp imx8mm_opps[] = { + DEFINE_OPP_NO_NODES(imx8mm_low_freq_clks, false), + DEFINE_OPP(imx8mm_audio_freq_clks, imx8mm_audio_freq_nodes, false), + DEFINE_OPP(imx8mm_high_freq_clks, imx8mm_high_freq_nodes, true), +}; + +static int imx8mm_busfreq_probe(struct platform_device *pdev) +{ + int ret; + + ret = busfreq_register(pdev, imx8mm_icc_nodes, + ARRAY_SIZE(imx8mm_icc_nodes), + imx8mm_opps, ARRAY_SIZE(imx8mm_opps)); + return ret; +} + +static int imx8mm_busfreq_remove(struct platform_device *pdev) +{ + return busfreq_unregister(pdev); +} + +static const struct of_device_id busfreq_of_match[] = { + { .compatible = "fsl,busfreq-imx8mm" }, + { }, +}; +MODULE_DEVICE_TABLE(of, busfreq_of_match); + +static struct platform_driver imx8mm_busfreq_driver = { + .probe = imx8mm_busfreq_probe, + .remove = imx8mm_busfreq_remove, + .driver = { + .name = "busfreq-imx8mm", + .of_match_table = busfreq_of_match, + }, +}; + +builtin_platform_driver(imx8mm_busfreq_driver); +MODULE_AUTHOR("Alexandre Bailon "); +MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/interconnect/imx8mm.h b/include/dt-bindings/interconnect/imx8mm.h new file mode 100644 index 000000000000..4318ed319edc --- /dev/null +++ b/include/dt-bindings/interconnect/imx8mm.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Interconnect framework driver for i.MX SoC + * + * Copyright (c) 2019, BayLibre + * Author: Alexandre Bailon + */ + +#ifndef __IMX8MM_INTERCONNECT_IDS_H +#define __IMX8MM_INTERCONNECT_IDS_H + +#define IMX8MM_NOC 0 +#define IMX8MM_CPU_0 1 +#define IMX8MM_CPU_1 2 +#define IMX8MM_CPU_2 3 +#define IMX8MM_CPU_3 4 +#define IMX8MM_VPU_H1 5 +#define IMX8MM_VPU_G1 6 +#define IMX8MM_VPU_G2 7 +#define IMX8MM_MIPI 8 +#define IMX8MM_USB_1 9 +#define IMX8MM_USB_2 10 +#define IMX8MM_PCIE 11 +#define IMX8MM_GPU 12 +#define IMX8MM_DRAM 13 + +#define IMX8MM_PL301 100 +#define IMX8MM_SAI1 101 +#define IMX8MM_SAI2 102 +#define IMX8MM_SAI3 103 +#define IMX8MM_SAI4 104 +#define IMX8MM_SAI5 105 +#define IMX8MM_SAI6 106 +#define IMX8MM_SPDIF 107 +#define IMX8MM_FEC 108 + +#endif /* __IMX8MM_INTERCONNECT_IDS_H */ From patchwork Wed Mar 13 19:34:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Bailon X-Patchwork-Id: 10851697 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1B1A51575 for ; Wed, 13 Mar 2019 19:33:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0756729BCB for ; Wed, 13 Mar 2019 19:33:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EF81029C4E; Wed, 13 Mar 2019 19:33:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 94A6A29BCB for ; Wed, 13 Mar 2019 19:33:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727538AbfCMTd4 (ORCPT ); Wed, 13 Mar 2019 15:33:56 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:45543 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727481AbfCMTdu (ORCPT ); Wed, 13 Mar 2019 15:33:50 -0400 Received: by mail-wr1-f67.google.com with SMTP id h99so3284485wrh.12 for ; Wed, 13 Mar 2019 12:33:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UDDK3ZuE18UBaMnSKNW3aRwC8Z//s3DoM8HiLpa/VRw=; b=SuP0zDPYF7Ulece5iTXk+pmnpyLWc3eKtMd3+JQD9+5ZSuuoyhbfZQZc8sUODuGHC5 JFC6ro1dq9n4/YzAHnyjlSsC2V8GvEfSBEAaJk+vR1ZAAhqA7jhJQX5fgPMWDpJ/jI6f fS0GjegeCK80Xf3Vs4VPYDIIvRxnnwA1VduNtWTULlzHJwd6KJcuGzSUfWiutkyI7VmQ veR1lv6BTzWDlUQypA8mI0X2Bj+s2a1Yw7rNQlWBawSnXlFb5+d6ZA+qh+FU0lDK5DPE BvLfqFrKbiVigytHRDh+O4RSElgR46/umz92BeeBB4l0OoGqS2APJMVE6TY2FqqlTENl nURA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UDDK3ZuE18UBaMnSKNW3aRwC8Z//s3DoM8HiLpa/VRw=; b=bcD7PRjmPWF5nkmn9qRdkx8I6WZ9mJY1o1sALhC5dZslCRJNDlInzIhnbRqXmoWqH4 xGkQZDmyAM3lEPXMJl4BN0mHn6veUNKQ29FEvQwYEkf+nsmFBogDSp+wOsiGPwQaFDem J3yyVfvxMpIrdK1Bq+BrjwHLaxYBx1LSK7R2AbaDBaGQAignZAbulHcuPVGtGXzpkpSz u+MpXqXEWdOiuKGr07Vi4rUOBwYSNQzs1oRHfeaJPg3n/4GOp/qGaFpgCPr+XWfoHlLy KqxzZIDsmLr0IDKhcG/46HID/K4aEtYhJBGwk7QRlRHZyzm6NChl/STRIXBQmPTtgUJt Gz5g== X-Gm-Message-State: APjAAAWlKKXJB25+7w9z/VC5sZA87Yb9ERcngfeeGLaXeb4BDGY90TsL AY24WWgvd1+QX4EYK9aOX/iiDNsnLTI= X-Google-Smtp-Source: APXvYqw3Ol5Hk3XjFB887ctA6G+qqgk2Oz8WuN2IY5XIz8KOcXb/f929xK7OrfCqOwiKJoS0VKAMMw== X-Received: by 2002:a5d:4a4d:: with SMTP id v13mr572670wrs.169.1552505628705; Wed, 13 Mar 2019 12:33:48 -0700 (PDT) Received: from localhost.localdomain (205.66.21.93.rev.sfr.net. [93.21.66.205]) by smtp.gmail.com with ESMTPSA id z198sm3017497wmc.10.2019.03.13.12.33.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 Mar 2019 12:33:47 -0700 (PDT) From: Alexandre Bailon To: linux-pm@vger.kernel.org, georgi.djakov@linaro.org Cc: mturquette@baylibre.com, ptitiano@baylibre.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, zening.wang@nxp.com, aisheng.dong@nxp.com, khilman@baylibre.com, ccaione@baylibre.com, Alexandre Bailon Subject: [RFC PATCH 3/3] dt-bindings: interconnect: Document fsl,busfreq-imx8mm bindings Date: Wed, 13 Mar 2019 20:34:08 +0100 Message-Id: <20190313193408.23740-4-abailon@baylibre.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190313193408.23740-1-abailon@baylibre.com> References: <20190313193408.23740-1-abailon@baylibre.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Document the device-tree bindings interconnect driver for i.MX8MM SoC. Signed-off-by: Alexandre Bailon --- .../bindings/interconnect/imx8mm.txt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/imx8mm.txt diff --git a/Documentation/devicetree/bindings/interconnect/imx8mm.txt b/Documentation/devicetree/bindings/interconnect/imx8mm.txt new file mode 100644 index 000000000000..81f0cf134de2 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/imx8mm.txt @@ -0,0 +1,24 @@ +i.MX busfreq driver binding +---------------------------------------------------- + +Required properties : +- compatible : must be "fsl,busfreq-imx8mm" +- #interconnect-cells : should contain 1 +- clocks : list of phandles and specifiers to all interconnect bus clocks +- clock-names : clock names must include "dram-alt", "dram-apb", "dram-core", + "noc", "ahb" and "axi" + +Examples: + + icc0: icc { + compatible = "fsl,busfreq-imx8mm"; + #interconnect-cells = <1>; + clocks = <&clk IMX8MM_CLK_DRAM_ALT>, + <&clk IMX8MM_CLK_DRAM_APB>, + <&clk IMX8MM_CLK_DRAM_CORE>, + <&clk IMX8MM_CLK_NOC_DIV>, + <&clk IMX8MM_CLK_AHB_DIV>, + <&clk IMX8MM_CLK_MAIN_AXI>; + clock-names = "dram-alt", "dram-apb", "dram-core", "noc", + "ahb", "axi"; + };