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: 10851701 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 E85B26C2 for ; Wed, 13 Mar 2019 19:34:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CB3D428A15 for ; Wed, 13 Mar 2019 19:34:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BEE8729D31; Wed, 13 Mar 2019 19:34:05 +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=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A83F328A15 for ; Wed, 13 Mar 2019 19:34:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=RXrl8E3wqopKPlYatp5csn/xWjhQFSyUXkrl0r4cev8=; b=UZ8MVt691t979/ g8rOrofjYG6ARpgZ/6E+qW1nAF+N+P/NwRfsIZ0DY+9N+drQATWfHALrJTgxvNBL4NRMO83vXslXC 8pmCMTZSpL5/ZG5MHguzzsZN0px/waFR4rgwkcbcThfRSPkVMTj/QPEU43KVc4Jt4w+DaQ9CnMZKK E+6NQpg7/splMLA0ARl5L9himbHVZmLrBMi3COJ7QkvJkoHTAbX6BRY+94F41SSe/GleA+XC08TAY TO2npGHp4WE3CKorViXVqB8fIOeMOCUCEbMR0Fr6ZC3XzOR8JRp1rFf9nflYpxxMkyplGEnvPU3Wy OG4l03+mn+qr/7Sk1Fkg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h49da-0005Qd-Fe; Wed, 13 Mar 2019 19:34:02 +0000 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1h49dM-0005DB-2G for linux-arm-kernel@lists.infradead.org; Wed, 13 Mar 2019 19:33:51 +0000 Received: by mail-wr1-x444.google.com with SMTP id y15so3315604wro.4 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=jJ8PvcvXuvIp1/KXw4fWLMyQWLsgRR4iC6NFMrdGfO1ssbpL113HM7Utu344d/e7Wx KxMIrmw5fKvrqpThXLOw+UFkLz7Q5i5cShJu/xoHMrCTaZO8nxngAtWwWoV30lITRyKK 6eu1s9IZAtjvxeXc0mT8RPJFLjsCaqGByHyEnsUloQfmGw+APiVRkFy5EAt2VgHMvZhB CoBVeXYrmGGx3MH5OG1KDOtdxL3D4mfsNheJtAsZ4gIj6KTVQLVd9BRIaxFK9hC/fC7e hdYuMC8oE0ORr3h5vBDpDAGR+pQjoCCMkNnmZJfFZQpYOPWL/qvFihXnaWz5/of8KkHW QYwA== X-Gm-Message-State: APjAAAUlbtn1ZDRkcY0wzUlOhgCwLHFvVNiDGKXbBbsZRFEYdlus+ngn hPCovDMp51o7Ij9gm3dCHisNqA== 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 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190313_123348_163038_BB88920B X-CRM114-Status: GOOD ( 25.44 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: aisheng.dong@nxp.com, ccaione@baylibre.com, khilman@baylibre.com, mturquette@baylibre.com, linux-kernel@vger.kernel.org, zening.wang@nxp.com, Alexandre Bailon , ptitiano@baylibre.com, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.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: 10851695 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 DD4ED1575 for ; Wed, 13 Mar 2019 19:33:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C54C729BCB for ; Wed, 13 Mar 2019 19:33:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B8C9129C4E; Wed, 13 Mar 2019 19:33:54 +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=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3A1F929BCB for ; Wed, 13 Mar 2019 19:33:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=EbNde05wi8ex+oLOJPAjr60Dg7tRUIuG9ICi2arleI0=; b=OGGJgdJonmqZ2M 3X7EV9CWlFRM9VU+2wvL9yzrvcU5iCPNZDxvSwB4sh+dnVZ/uW37Ev/UEb0KEYe6SNslpJ59MwFU4 XnXchBwYES0GI3jRMSrsLJz3fr+Lg/8Y1KOuEe/BKd3o0lMRTWQOwMxn5imX7JATvHCQGAJdSBLB0 oFyORf+Srg1+zNmdygPr8Wwf/W3H/KNTxw2cs0yhMn+SWQCNcC/qygwJxdjoQQv0h2xHoDZveTFq0 VkEegP/FbPxoGepus+Jc7PujzxbKbo3pmK+fjyQJiWRhhAyQX18jFI16NjbVcSf5gI/mGcoJ6VFTs xbxAE75fZntOt3TtqmAw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h49dQ-0005Ev-MM; Wed, 13 Mar 2019 19:33:52 +0000 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1h49dM-0005DD-G6 for linux-arm-kernel@lists.infradead.org; Wed, 13 Mar 2019 19:33:50 +0000 Received: by mail-wr1-x441.google.com with SMTP id y15so3315663wro.4 for ; Wed, 13 Mar 2019 12:33:48 -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=hUlVYwzJzwIbjQjwDS5TQx6X/i6CJoQWme/9vVElg9WI0k6MN0yqfli9Qg6g4oxjOW sDF4UYsTPKnfRCe2YXA7b+xVhz7meM5LC8uiv7qAemvogiuuzXBd4okvWIGwi7uMk1yn njo7M3xTrAfRg9F/qP7qKTVIGElQSM9SiZTth41fabfx5DuZ9zqc/+WJZaN9a3TD5L5L nD5+16a/u+gUwtl8zmso31a2iXy/3DdVswhwtmub5cyTZ/7kpuMuVylUAy8M31AfzXLM TIuWunW8CKzckZcJ2V8e7GKqtR2At49bBP2+t9t/6VKJoLMEzP3ZQziZXKuyetO1v1sd ss7A== X-Gm-Message-State: APjAAAUT7hBhh5svQYQfWTFJ7WHbNO1F1stKv0e0bUhZ8F9I+mdPjWMs BKH43RL+/VrrJxeJ5yq4V9Y/WA== 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 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190313_123348_538955_9D40BA6D X-CRM114-Status: GOOD ( 17.57 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: aisheng.dong@nxp.com, ccaione@baylibre.com, khilman@baylibre.com, mturquette@baylibre.com, linux-kernel@vger.kernel.org, zening.wang@nxp.com, Alexandre Bailon , ptitiano@baylibre.com, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.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: 10851707 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 CD90E6C2 for ; Wed, 13 Mar 2019 19:34:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E11B529B4E for ; Wed, 13 Mar 2019 19:34:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D530B29D31; Wed, 13 Mar 2019 19:34:27 +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=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7C5B329B4E for ; Wed, 13 Mar 2019 19:34:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=hXY9f9xTcLg2Ci3dv/fk0YQ38ioMiDgfy5rUOnSPk28=; b=A/11c/xVB+k8m6 fUn0yNxGrDJQMjEeJLrFpYjDxmV46W9WnXDs2O/8zduU3Mkn20Ky2TxZR8XH9ccWDWPTkB8YBxYXF EywUJik5b8Iu3Dvjr5lf3rqAF5o19TgQZosdGQpJA7lVyCey+S+yGLupw/VVbAyCjDR/O/kl+Yfzg X7+j+AoAF0Us3lH2OQtEIJa3CMT5bkg8tXRhcUj5RtKt/t+W014nq68Ji9EC64vEfjJHPfy3OHqVN rOaalY9cjBf/ClDBZIpUZoiyF8dxL5RbLaOzrQyKNn9NmpEVHOsw21TkB1rmetEmVg4N+D5Liwo/l VoYa5mP3sYzU/cGUaq4g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h49dw-0005wL-Me; Wed, 13 Mar 2019 19:34:24 +0000 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1h49dN-0005Dk-Uo for linux-arm-kernel@lists.infradead.org; Wed, 13 Mar 2019 19:33:51 +0000 Received: by mail-wr1-x441.google.com with SMTP id w2so3287056wrt.11 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=alsBU/tTI8loivK7qCJVfZ5Un0cyqKnTL7jiYKOqgjCS2LNTSZwrTjOn5bFLoAOFsb zKzHUtPfESgQLdQmhuODbtu6yW6Ia2oyLju045F+cW0A9LP0ME1lYtaAoTdFQl14Rixo OpstmSIq9ydJCQWnq/a0DZe6Ils9anJ4cqG9gzDVCELrdS28vI9J1an5FuhO/wGHpUml c2EinvMyXn+YmqUAQDyeLzOq/REir7eVcKIwQFcbDhqDwjo+Jb27ffL0DMSVfxR41HxS 7ecgmTLyHKi3JhIddmUZV3DZqAvCD+Lsey6Xyz47srO3mHhB1a6OlwjlA9sQrYm04yZg Ys9w== X-Gm-Message-State: APjAAAVyQrj5sy2A6PMeM2Il+aVca0qEZUmxhqjZYNS6ZshbxC+jBQ0Q DFZ4iE7Nt2pzlmr4c6GPPuIUjg== 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 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190313_123349_992443_742BF110 X-CRM114-Status: GOOD ( 10.88 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: aisheng.dong@nxp.com, ccaione@baylibre.com, khilman@baylibre.com, mturquette@baylibre.com, linux-kernel@vger.kernel.org, zening.wang@nxp.com, Alexandre Bailon , ptitiano@baylibre.com, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.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"; + };