From patchwork Fri Aug 10 14:52:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562799 X-Patchwork-Delegate: agross@codeaurora.org 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 A8AC21515 for ; Fri, 10 Aug 2018 14:53:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 960FA2B581 for ; Fri, 10 Aug 2018 14:53:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8A36A2BA9A; Fri, 10 Aug 2018 14:53:43 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable 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 1BB6E2B581 for ; Fri, 10 Aug 2018 14:53:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727445AbeHJRXx (ORCPT ); Fri, 10 Aug 2018 13:23:53 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:33798 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728271AbeHJRXA (ORCPT ); Fri, 10 Aug 2018 13:23:00 -0400 Received: by mail-wm0-f67.google.com with SMTP id l2-v6so1695022wme.1 for ; Fri, 10 Aug 2018 07:52:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3oltLqGMpD1j1mfioWk+wn2DTufVbquuCtG8B9CVxjQ=; b=j+QQQWACyF5AmU5k0NTzeMPuDUCun8AZqMEoj7YBh46bl03Vd++0JhM/67vl7wPbG7 NEVxuQNp1N98qL6mupKEj0GKpj0P0Ok+63IFYFNzuuMioQc9ArjV1kql0/TPW7R0/VU2 t9T9BTbMgVUkoDm8LRmMQhKt2/hPmHC3299y8= 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; bh=3oltLqGMpD1j1mfioWk+wn2DTufVbquuCtG8B9CVxjQ=; b=kCESKkk7voLM4KQZ5BIPLeuIQ3kfPdF/eL3xuBJ09qByyIFQHawHV01AudRDFlSObk Iz9cXUf+z9jFatG74EDLN1Rr4JZU2nqWKPpt3HLIrdvY8+eUGiMCkBezXnESv1Y4Ss4q wtL2Laf15aP4nlWj6srIxdpGYU4ql9u8QSmOz++ojJsCpOelhL7/kGicv+/GHhBJF5v7 zXa3UY2Usf7wlYitPr2W94yhPQKmj9NIRY0OzDzRQ6/81PChHBFqL3jAXz9Jqc0KwMPX N8b8lEgD8ohqT5oFksJ7ZsEgR3s5eGvHb8g3jneuOVbvVAIPl4TPI7/3eLrpNm+QNjI/ cB3Q== X-Gm-Message-State: AOUpUlFL4bC1TY+FeiZQqt9X+h95fScLuAnUJZOABm72PX6A/2ghnAqn 0z/B/shrYlfhsWsYw2YwQRbSGg== X-Google-Smtp-Source: AA+uWPwXz7zwj6UIOuRVwMIcC1r3d0IqclxJ8kgqBuRY7xtl78VblHu0NUbcUR1mBhbhprlcr2CkMw== X-Received: by 2002:a1c:2dc8:: with SMTP id t191-v6mr1815964wmt.94.1533912764668; Fri, 10 Aug 2018 07:52:44 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:43 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 1/8] interconnect: Add generic on-chip interconnect API Date: Fri, 10 Aug 2018 17:52:26 +0300 Message-Id: <20180810145233.16466-2-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch introduces a new API to get requirements and configure the interconnect buses across the entire chipset to fit with the current demand. The API is using a consumer/provider-based model, where the providers are the interconnect buses and the consumers could be various drivers. The consumers request interconnect resources (path) between endpoints and set the desired constraints on this data flow path. The providers receive requests from consumers and aggregate these requests for all master-slave pairs on that path. Then the providers configure each participating in the topology node according to the requested data flow path, physical links and constraints. The topology could be complicated and multi-tiered and is SoC specific. Signed-off-by: Georgi Djakov Reviewed-by: Evan Green --- Documentation/interconnect/interconnect.rst | 94 ++++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/interconnect/Kconfig | 10 + drivers/interconnect/Makefile | 2 + drivers/interconnect/core.c | 573 ++++++++++++++++++++ include/linux/interconnect-provider.h | 125 +++++ include/linux/interconnect.h | 42 ++ 8 files changed, 849 insertions(+) create mode 100644 Documentation/interconnect/interconnect.rst create mode 100644 drivers/interconnect/Kconfig create mode 100644 drivers/interconnect/Makefile create mode 100644 drivers/interconnect/core.c create mode 100644 include/linux/interconnect-provider.h create mode 100644 include/linux/interconnect.h diff --git a/Documentation/interconnect/interconnect.rst b/Documentation/interconnect/interconnect.rst new file mode 100644 index 000000000000..b8107dcc4cd3 --- /dev/null +++ b/Documentation/interconnect/interconnect.rst @@ -0,0 +1,94 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================================== +GENERIC SYSTEM INTERCONNECT SUBSYSTEM +===================================== + +Introduction +------------ + +This framework is designed to provide a standard kernel interface to control +the settings of the interconnects on an SoC. These settings can be throughput, +latency and priority between multiple interconnected devices or functional +blocks. This can be controlled dynamically in order to save power or provide +maximum performance. + +The interconnect bus is hardware with configurable parameters, which can be +set on a data path according to the requests received from various drivers. +An example of interconnect buses are the interconnects between various +components or functional blocks in chipsets. There can be multiple interconnects +on an SoC that can be multi-tiered. + +Below is a simplified diagram of a real-world SoC interconnect bus topology. + +:: + + +----------------+ +----------------+ + | HW Accelerator |--->| M NoC |<---------------+ + +----------------+ +----------------+ | + | | +------------+ + +-----+ +-------------+ V +------+ | | + | DDR | | +--------+ | PCIe | | | + +-----+ | | Slaves | +------+ | | + ^ ^ | +--------+ | | C NoC | + | | V V | | + +------------------+ +------------------------+ | | +-----+ + | |-->| |-->| |-->| CPU | + | |-->| |<--| | +-----+ + | Mem NoC | | S NoC | +------------+ + | |<--| |---------+ | + | |<--| |<------+ | | +--------+ + +------------------+ +------------------------+ | | +-->| Slaves | + ^ ^ ^ ^ ^ | | +--------+ + | | | | | | V + +------+ | +-----+ +-----+ +---------+ +----------------+ +--------+ + | CPUs | | | GPU | | DSP | | Masters |-->| P NoC |-->| Slaves | + +------+ | +-----+ +-----+ +---------+ +----------------+ +--------+ + | + +-------+ + | Modem | + +-------+ + +Terminology +----------- + +Interconnect provider is the software definition of the interconnect hardware. +The interconnect providers on the above diagram are M NoC, S NoC, C NoC, P NoC +and Mem NoC. + +Interconnect node is the software definition of the interconnect hardware +port. Each interconnect provider consists of multiple interconnect nodes, +which are connected to other SoC components including other interconnect +providers. The point on the diagram where the CPUs connect to the memory is +called an interconnect node, which belongs to the Mem NoC interconnect provider. + +Interconnect endpoints are the first or the last element of the path. Every +endpoint is a node, but not every node is an endpoint. + +Interconnect path is everything between two endpoints including all the nodes +that have to be traversed to reach from a source to destination node. It may +include multiple master-slave pairs across several interconnect providers. + +Interconnect consumers are the entities which make use of the data paths exposed +by the providers. The consumers send requests to providers requesting various +throughput, latency and priority. Usually the consumers are device drivers, that +send request based on their needs. An example for a consumer is a video decoder +that supports various formats and image sizes. + +Interconnect providers +---------------------- + +Interconnect provider is an entity that implements methods to initialize and +configure interconnect bus hardware. The interconnect provider drivers should +be registered with the interconnect provider core. + +.. kernel-doc:: include/linux/interconnect-provider.h + +Interconnect consumers +---------------------- + +Interconnect consumers are the clients which use the interconnect APIs to +get paths between endpoints and set their bandwidth/latency/QoS requirements +for these interconnect paths. + +.. kernel-doc:: include/linux/interconnect.h diff --git a/drivers/Kconfig b/drivers/Kconfig index 95b9ccc08165..3ed6ede9d021 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -217,4 +217,6 @@ source "drivers/siox/Kconfig" source "drivers/slimbus/Kconfig" +source "drivers/interconnect/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 24cd47014657..0cca95740d9b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -185,3 +185,4 @@ obj-$(CONFIG_TEE) += tee/ obj-$(CONFIG_MULTIPLEXER) += mux/ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ obj-$(CONFIG_SIOX) += siox/ +obj-$(CONFIG_INTERCONNECT) += interconnect/ diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig new file mode 100644 index 000000000000..a261c7d41deb --- /dev/null +++ b/drivers/interconnect/Kconfig @@ -0,0 +1,10 @@ +menuconfig INTERCONNECT + tristate "On-Chip Interconnect management support" + help + Support for management of the on-chip interconnects. + + This framework is designed to provide a generic interface for + managing the interconnects in a SoC. + + If unsure, say no. + diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile new file mode 100644 index 000000000000..97fca2e09d24 --- /dev/null +++ b/drivers/interconnect/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_INTERCONNECT) += core.o diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c new file mode 100644 index 000000000000..9ca39aca4982 --- /dev/null +++ b/drivers/interconnect/core.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Interconnect framework core driver + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDR(icc_idr); +static LIST_HEAD(icc_provider_list); +static DEFINE_MUTEX(icc_lock); + +/** + * struct icc_req - constraints that are attached to each node + * + * @req_node: entry in list of requests for the particular @node + * @node: the interconnect node to which this constraint applies + * @dev: reference to the device that sets the constraints + * @avg_bw: an integer describing the average bandwidth in kbps + * @peak_bw: an integer describing the peak bandwidth in kbps + */ +struct icc_req { + struct hlist_node req_node; + struct icc_node *node; + struct device *dev; + u32 avg_bw; + u32 peak_bw; +}; + +/** + * struct icc_path - interconnect path structure + * @num_nodes: number of hops (nodes) + * @reqs: array of the requests applicable to this path of nodes + */ +struct icc_path { + size_t num_nodes; + struct icc_req reqs[]; +}; + +static struct icc_node *node_find(const int id) +{ + return idr_find(&icc_idr, id); +} + +static struct icc_path *path_init(struct device *dev, struct icc_node *dst, + ssize_t num_nodes) +{ + struct icc_node *node = dst; + struct icc_path *path; + int i; + + path = kzalloc(struct_size(path, reqs, num_nodes), GFP_KERNEL); + if (!path) + return ERR_PTR(-ENOMEM); + + path->num_nodes = num_nodes; + + for (i = num_nodes - 1; i >= 0; i--) { + node->provider->users++; + hlist_add_head(&path->reqs[i].req_node, &node->req_list); + path->reqs[i].node = node; + path->reqs[i].dev = dev; + /* reference to previous node was saved during path traversal */ + node = node->reverse; + } + + return path; +} + +static struct icc_path *path_find(struct device *dev, struct icc_node *src, + struct icc_node *dst) +{ + struct icc_path *path = ERR_PTR(-EPROBE_DEFER); + struct icc_node *n, *node = NULL; + struct list_head traverse_list; + struct list_head edge_list; + struct list_head visited_list; + size_t i, depth = 1; + bool found = false; + + INIT_LIST_HEAD(&traverse_list); + INIT_LIST_HEAD(&edge_list); + INIT_LIST_HEAD(&visited_list); + + list_add(&src->search_list, &traverse_list); + src->reverse = NULL; + + do { + list_for_each_entry_safe(node, n, &traverse_list, search_list) { + if (node == dst) { + found = true; + list_splice_init(&edge_list, &visited_list); + list_splice_init(&traverse_list, &visited_list); + break; + } + for (i = 0; i < node->num_links; i++) { + struct icc_node *tmp = node->links[i]; + + if (!tmp) { + path = ERR_PTR(-ENOENT); + goto out; + } + + if (tmp->is_traversed) + continue; + + tmp->is_traversed = true; + tmp->reverse = node; + list_add_tail(&tmp->search_list, &edge_list); + } + } + + if (found) + break; + + list_splice_init(&traverse_list, &visited_list); + list_splice_init(&edge_list, &traverse_list); + + /* count the hops including the source */ + depth++; + + } while (!list_empty(&traverse_list)); + +out: + + /* reset the traversed state */ + list_for_each_entry_reverse(n, &visited_list, search_list) + n->is_traversed = false; + + if (found) + path = path_init(dev, dst, depth); + + return path; +} + +/* + * We want the path to honor all bandwidth requests, so the average and peak + * bandwidth requirements from each consumer are aggregated at each node. + */ + +static int aggregate_requests(struct icc_node *node) +{ + struct icc_provider *p = node->provider; + struct icc_req *r; + + node->avg_bw = 0; + node->peak_bw = 0; + + hlist_for_each_entry(r, &node->req_list, req_node) + p->aggregate(node, r->avg_bw, r->peak_bw, + &node->avg_bw, &node->peak_bw); + + return 0; +} + +static int apply_constraints(struct icc_path *path) +{ + struct icc_node *next, *prev = NULL; + int ret; + int i; + + for (i = 0; i < path->num_nodes; i++, prev = next) { + struct icc_provider *p; + + next = path->reqs[i].node; + /* + * Both endpoints should be valid master-slave pairs of the + * same interconnect provider that will be configured. + */ + if (!prev || next->provider != prev->provider) + continue; + + p = next->provider; + + /* set the constraints */ + ret = p->set(prev, next); + if (ret) + goto out; + } +out: + return ret; +} + +/** + * icc_set() - set constraints on an interconnect path between two endpoints + * @path: reference to the path returned by icc_get() + * @avg_bw: average bandwidth in kbps + * @peak_bw: peak bandwidth in kbps + * + * This function is used by an interconnect consumer to express its own needs + * in terms of bandwidth for a previously requested path between two endpoints. + * The requests are aggregated and each node is updated accordingly. The entire + * path is locked by a mutex to ensure that the set() is completed. + * The @path can be NULL when the "interconnects" DT properties is missing, + * which will mean that no constraints will be set. + * + * Returns 0 on success, or an appropriate error code otherwise. + */ +int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw) +{ + struct icc_node *node; + struct icc_provider *p; + size_t i; + int ret; + + if (!path) + return 0; + + mutex_lock(&icc_lock); + + for (i = 0; i < path->num_nodes; i++) { + node = path->reqs[i].node; + p = node->provider; + + /* update the consumer request for this path */ + path->reqs[i].avg_bw = avg_bw; + path->reqs[i].peak_bw = peak_bw; + + /* aggregate requests for this node */ + aggregate_requests(node); + } + + ret = apply_constraints(path); + if (ret) + pr_err("interconnect: error applying constraints (%d)", ret); + + mutex_unlock(&icc_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_set); + +/** + * icc_get() - return a handle for path between two endpoints + * @dev: the device requesting the path + * @src_id: source device port id + * @dst_id: destination device port id + * + * This function will search for a path between two endpoints and return an + * icc_path handle on success. Use icc_put() to release + * constraints when they are not needed anymore. + * If the interconnect API is disabled, NULL is returned and the consumer + * drivers will still build. Drivers are free to handle this specifically, + * but they don't have to. + * + * Return: icc_path pointer on success, ERR_PTR() on error or NULL if the + * interconnect API is disabled. + */ +struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id) +{ + struct icc_node *src, *dst; + struct icc_path *path = ERR_PTR(-EPROBE_DEFER); + + mutex_lock(&icc_lock); + + src = node_find(src_id); + if (!src) + goto out; + + dst = node_find(dst_id); + if (!dst) + goto out; + + path = path_find(dev, src, dst); + if (IS_ERR(path)) + dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); + +out: + mutex_unlock(&icc_lock); + return path; +} +EXPORT_SYMBOL_GPL(icc_get); + +/** + * icc_put() - release the reference to the icc_path + * @path: interconnect path + * + * Use this function to release the constraints on a path when the path is + * no longer needed. The constraints will be re-aggregated. + */ +void icc_put(struct icc_path *path) +{ + struct icc_node *node; + size_t i; + int ret; + + if (!path || WARN_ON(IS_ERR(path))) + return; + + ret = icc_set(path, 0, 0); + if (ret) + pr_err("%s: error (%d)\n", __func__, ret); + + mutex_lock(&icc_lock); + for (i = 0; i < path->num_nodes; i++) { + node = path->reqs[i].node; + hlist_del(&path->reqs[i].req_node); + if (!WARN_ON(!node->provider->users)) + node->provider->users--; + } + mutex_unlock(&icc_lock); + + kfree(path); +} +EXPORT_SYMBOL_GPL(icc_put); + +static struct icc_node *icc_node_create_nolock(int id) +{ + struct icc_node *node; + + /* check if node already exists */ + node = node_find(id); + if (node) + goto out; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + node = ERR_PTR(-ENOMEM); + goto out; + } + + id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL); + if (WARN(id < 0, "couldn't get idr")) { + kfree(node); + node = ERR_PTR(id); + goto out; + } + + node->id = id; + +out: + return node; +} + +/** + * icc_node_create() - create a node + * @id: node id + * + * Return: icc_node pointer on success, or ERR_PTR() on error + */ +struct icc_node *icc_node_create(int id) +{ + struct icc_node *node; + + mutex_lock(&icc_lock); + + node = icc_node_create_nolock(id); + + mutex_unlock(&icc_lock); + + return node; +} +EXPORT_SYMBOL_GPL(icc_node_create); + +/** + * icc_node_destroy() - destroy a node + * @id: node id + * + */ +void icc_node_destroy(int id) +{ + struct icc_node *node; + + mutex_lock(&icc_lock); + + node = node_find(id); + if (node) { + idr_remove(&icc_idr, node->id); + WARN_ON(!hlist_empty(&node->req_list)); + } + + mutex_unlock(&icc_lock); + + kfree(node); +} +EXPORT_SYMBOL_GPL(icc_node_destroy); + +/** + * icc_link_create() - create a link between two nodes + * @src_id: source node id + * @dst_id: destination node id + * + * Create a link between two nodes. The nodes might belong to different + * interconnect providers and the @dst_id node might not exist (if the + * provider driver has not probed yet). So just create the @dst_id node + * and when the actual provider driver is probed, the rest of the node + * data is filled. + * + * Return: 0 on success, or an error code otherwise + */ +int icc_link_create(struct icc_node *node, const int dst_id) +{ + struct icc_node *dst; + struct icc_node **new; + int ret = 0; + + if (!node->provider) + return -EINVAL; + + mutex_lock(&icc_lock); + + dst = node_find(dst_id); + if (!dst) { + dst = icc_node_create_nolock(dst_id); + + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); + goto out; + } + } + + new = krealloc(node->links, + (node->num_links + 1) * sizeof(*node->links), + GFP_KERNEL); + if (!new) { + ret = -ENOMEM; + goto out; + } + + node->links = new; + node->links[node->num_links++] = dst; + +out: + mutex_unlock(&icc_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_link_create); + +/** + * icc_link_destroy() - destroy a link between two nodes + * @src: pointer to source node + * @dst: pointer to destination node + * + * Return: 0 on success, or an error code otherwise + */ +int icc_link_destroy(struct icc_node *src, struct icc_node *dst) +{ + struct icc_node **new; + size_t slot; + int ret = 0; + + if (IS_ERR_OR_NULL(src)) + return -EINVAL; + + if (IS_ERR_OR_NULL(dst)) + return -EINVAL; + + mutex_lock(&icc_lock); + + for (slot = 0; slot < src->num_links; slot++) + if (src->links[slot] == dst) + break; + + if (WARN_ON(slot == src->num_links)) { + ret = -ENXIO; + goto out; + } + + src->links[slot] = src->links[--src->num_links]; + + new = krealloc(src->links, + (src->num_links) * sizeof(*src->links), + GFP_KERNEL); + if (new) + src->links = new; + +out: + mutex_unlock(&icc_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_link_destroy); + +/** + * icc_node_add() - add interconnect node to interconnect provider + * @node: pointer to the interconnect node + * @provider: pointer to the interconnect provider + * + */ +void icc_node_add(struct icc_node *node, struct icc_provider *provider) +{ + mutex_lock(&icc_lock); + + node->provider = provider; + list_add(&node->node_list, &provider->nodes); + + mutex_unlock(&icc_lock); +} +EXPORT_SYMBOL_GPL(icc_node_add); + +/** + * icc_node_del() - delete interconnect node from interconnect provider + * @node: pointer to the interconnect node + * + */ +void icc_node_del(struct icc_node *node) +{ + mutex_lock(&icc_lock); + + list_del(&node->node_list); + + mutex_unlock(&icc_lock); +} +EXPORT_SYMBOL_GPL(icc_node_del); + +/** + * icc_provider_add() - add a new interconnect provider + * @icc_provider: the interconnect provider that will be added into topology + * + * Return: 0 on success, or an error code otherwise + */ +int icc_provider_add(struct icc_provider *provider) +{ + if (WARN_ON(!provider->set)) + return -EINVAL; + + mutex_lock(&icc_lock); + + INIT_LIST_HEAD(&provider->nodes); + list_add(&provider->provider_list, &icc_provider_list); + + mutex_unlock(&icc_lock); + + dev_dbg(provider->dev, "interconnect provider added to topology\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(icc_provider_add); + +/** + * icc_provider_del() - delete previously added interconnect provider + * @icc_provider: the interconnect provider that will be removed from topology + * + * Return: 0 on success, or an error code otherwise + */ +int icc_provider_del(struct icc_provider *provider) +{ + mutex_lock(&icc_lock); + if (provider->users) { + pr_warn("interconnect provider still has %d users\n", + provider->users); + mutex_unlock(&icc_lock); + return -EBUSY; + } + + if (!list_empty(&provider->nodes)) { + pr_warn("interconnect provider still has nodes\n"); + mutex_unlock(&icc_lock); + return -EBUSY; + } + + list_del(&provider->provider_list); + mutex_unlock(&icc_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(icc_provider_del); + +MODULE_AUTHOR("Georgi Djakov + */ + +#ifndef _LINUX_INTERCONNECT_PROVIDER_H +#define _LINUX_INTERCONNECT_PROVIDER_H + +#include + +#define icc_units_to_bps(bw) ((bw) * 1000ULL) + +struct icc_node; + +/** + * struct icc_provider - interconnect provider (controller) entity that might + * provide multiple interconnect controls + * + * @provider_list: list of the registered interconnect providers + * @nodes: internal list of the interconnect provider nodes + * @set: pointer to device specific set operation function + * @aggregate: pointer to device specific aggregate operation function + * @dev: the device this interconnect provider belongs to + * @users: count of active users + * @data: pointer to private data + */ +struct icc_provider { + struct list_head provider_list; + struct list_head nodes; + int (*set)(struct icc_node *src, struct icc_node *dst); + int (*aggregate)(struct icc_node *node, u32 avg_bw, u32 peak_bw, + u32 *agg_avg, u32 *agg_peak); + struct device *dev; + int users; + void *data; +}; + +/** + * struct icc_node - entity that is part of the interconnect topology + * + * @id: platform specific node id + * @name: node name used in debugfs + * @links: a list of targets pointing to where we can go next when traversing + * @num_links: number of links to other interconnect nodes + * @provider: points to the interconnect provider of this node + * @node_list: the list entry in the parent provider's "nodes" list + * @search_list: list used when walking the nodes graph + * @reverse: pointer to previous node when walking the nodes graph + * @is_traversed: flag that is used when walking the nodes graph + * @req_list: a list of QoS constraint requests associated with this node + * @avg_bw: aggregated value of average bandwidth requests from all consumers + * @peak_bw: aggregated value of peak bandwidth requests from all consumers + * @data: pointer to private data + */ +struct icc_node { + int id; + const char *name; + struct icc_node **links; + size_t num_links; + + struct icc_provider *provider; + struct list_head node_list; + struct list_head search_list; + struct icc_node *reverse; + bool is_traversed; + struct hlist_head req_list; + u32 avg_bw; + u32 peak_bw; + void *data; +}; + +#if IS_ENABLED(CONFIG_INTERCONNECT) + +struct icc_node *icc_node_create(int id); +void icc_node_destroy(int id); +int icc_link_create(struct icc_node *node, const int dst_id); +int icc_link_destroy(struct icc_node *src, struct icc_node *dst); +void icc_node_add(struct icc_node *node, struct icc_provider *provider); +void icc_node_del(struct icc_node *node); +int icc_provider_add(struct icc_provider *provider); +int icc_provider_del(struct icc_provider *provider); + +#else + +static inline struct icc_node *icc_node_create(int id) +{ + return ERR_PTR(-ENOTSUPP); +} + +void icc_node_destroy(int id) +{ +} + +static inline int icc_link_create(struct icc_node *node, const int dst_id) +{ + return -ENOTSUPP; +} + +int icc_link_destroy(struct icc_node *src, struct icc_node *dst) +{ + return -ENOTSUPP; +} + +void icc_node_add(struct icc_node *node, struct icc_provider *provider) +{ +} + +void icc_node_del(struct icc_node *node) +{ +} + +static inline int icc_provider_add(struct icc_provider *provider) +{ + return -ENOTSUPP; +} + +static inline int icc_provider_del(struct icc_provider *provider) +{ + return -ENOTSUPP; +} + +#endif /* CONFIG_INTERCONNECT */ + +#endif /* _LINUX_INTERCONNECT_PROVIDER_H */ diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h new file mode 100644 index 000000000000..593215371fd6 --- /dev/null +++ b/include/linux/interconnect.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov + */ + +#ifndef _LINUX_INTERCONNECT_H +#define _LINUX_INTERCONNECT_H + +#include +#include + +struct icc_path; +struct device; + +#if IS_ENABLED(CONFIG_INTERCONNECT) + +struct icc_path *icc_get(struct device *dev, const int src_id, + const int dst_id); +void icc_put(struct icc_path *path); +int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw); + +#else + +static inline struct icc_path *icc_get(struct device *dev, const int src_id, + const int dst_id) +{ + return NULL; +} + +static inline void icc_put(struct icc_path *path) +{ +} + +static inline int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw) +{ + return 0; +} + +#endif /* CONFIG_INTERCONNECT */ + +#endif /* _LINUX_INTERCONNECT_H */ From patchwork Fri Aug 10 14:52:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562765 X-Patchwork-Delegate: agross@codeaurora.org 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 2C9E61515 for ; Fri, 10 Aug 2018 14:52:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19C072BC36 for ; Fri, 10 Aug 2018 14:52:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 09A602BC4E; Fri, 10 Aug 2018 14:52:50 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 989502BC36 for ; Fri, 10 Aug 2018 14:52:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728299AbeHJRXB (ORCPT ); Fri, 10 Aug 2018 13:23:01 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:40507 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728283AbeHJRXB (ORCPT ); Fri, 10 Aug 2018 13:23:01 -0400 Received: by mail-wr1-f67.google.com with SMTP id h15-v6so8551996wrs.7 for ; Fri, 10 Aug 2018 07:52:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Wpwh1J0n/D8S9rbxdqkayW0bLbU11ULq+GMS5dW7EjU=; b=alG8SUHlrGlrBguXp0OwUd+5ntlokkyoAptgeDfts5gxy1ZiFBgd3oVCKCcSMaChS+ 2kx8KgB6MDTKjmevMOINUJjHvklVYHSDPAE6Ky4jNsMLYET4eYH5Q8tFBRU+CTDLxSsc AeJb295UnxuH4Y0ipoepMDmkzHSCfQ2Nn8NE4= 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; bh=Wpwh1J0n/D8S9rbxdqkayW0bLbU11ULq+GMS5dW7EjU=; b=dYZiLQrrPKd8tbLSIcWYyAHvMQMZkICEphmYX4SwPz11zWBvDiaveXA7Q9GXs/Puoa O+BaSmL9YM1A5dZcDF1YEEKa6BR2/pSvSM5PWDQFX/KiiasSh1r9IQScVuSP2nY5NA/0 YHym5Ol9RXG65Upq2P/FYPpmIqTQl8LpeKtc9EXzQQIDT2CVcal2KnmlcCsIj2vp9JZn kKJmzISqASu3Q33BCEvRo2VfPTnLpq1E85q3kbURbZHQ8QY8l1US+ZO3DG0MAF6cOO53 dtWaBVBoFUoCSH/KcDReXrE2dmyN+huofoN3+NlOR7tOxPhz2MFrIgJsjyxvHgvLPat8 bCMA== X-Gm-Message-State: AOUpUlFJ68myVsLT6SPkVhYu7mC3IMKKc2RfvcFESd2qviV+F/AIceOH 5hLAKDKEl3kpojt5iKjyJYcGAdMqy0U= X-Google-Smtp-Source: AA+uWPx1903AUYi6JtmezKEXa8XRio4UsXD7xO+QJ2IS6JJL/li8Qhw3nAwXOmWkxB1l/wpdPCSUcA== X-Received: by 2002:adf:bf10:: with SMTP id p16-v6mr4324454wrh.235.1533912766599; Fri, 10 Aug 2018 07:52:46 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:45 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 2/8] dt-bindings: Introduce interconnect binding Date: Fri, 10 Aug 2018 17:52:27 +0300 Message-Id: <20180810145233.16466-3-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This binding is intended to represent the relations between the interconnect controllers (providers) and consumer device nodes. It will allow creating links between consumers and interconnect paths (exposed by interconnect providers). Signed-off-by: Georgi Djakov --- .../bindings/interconnect/interconnect.txt | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/interconnect.txt diff --git a/Documentation/devicetree/bindings/interconnect/interconnect.txt b/Documentation/devicetree/bindings/interconnect/interconnect.txt new file mode 100644 index 000000000000..5cb7d3c8d44d --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/interconnect.txt @@ -0,0 +1,60 @@ +Interconnect Provider Device Tree Bindings +========================================= + +The purpose of this document is to define a common set of generic interconnect +providers/consumers properties. + + += interconnect providers = + +The interconnect provider binding is intended to represent the interconnect +controllers in the system. Each provider registers a set of interconnect +nodes, which expose the interconnect related capabilities of the interconnect +to consumer drivers. These capabilities can be throughput, latency, priority +etc. The consumer drivers set constraints on interconnect path (or endpoints) +depending on the use case. Interconnect providers can also be interconnect +consumers, such as in the case where two network-on-chip fabrics interface +directly + +Required properties: +- compatible : contains the interconnect provider compatible string +- #interconnect-cells : number of cells in a interconnect specifier needed to + encode the interconnect node id + +Example: + + snoc: snoc@580000 { + compatible = "qcom,msm8916-snoc"; + #interconnect-cells = <1>; + reg = <0x580000 0x14000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + }; + + += interconnect consumers = + +The interconnect consumers are device nodes which dynamically express their +bandwidth requirements along interconnect paths they are connected to. There +can be multiple interconnect providers on a SoC and the consumer may consume +multiple paths from different providers depending on use case and the +components it has to interact with. + +Required properties: +interconnects : Pairs of phandles and interconnect provider specifier to denote + the edge source and destination ports of the interconnect path. + +Optional properties: +interconnect-names : List of interconnect path name strings sorted in the same + order as the interconnects property. Consumers drivers will use + interconnect-names to match interconnect paths with interconnect + specifiers. + +Example: + + sdhci@7864000 { + ... + interconnects = <&pnoc MASTER_SDCC_1 &bimc SLAVE_EBI_CH0>; + interconnect-names = "ddr"; + }; From patchwork Fri Aug 10 14:52:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562793 X-Patchwork-Delegate: agross@codeaurora.org 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 315C013BB for ; Fri, 10 Aug 2018 14:53:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 222782B581 for ; Fri, 10 Aug 2018 14:53:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 15B7B2B9E1; Fri, 10 Aug 2018 14:53:29 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable 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 A534A2B581 for ; Fri, 10 Aug 2018 14:53:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728467AbeHJRXE (ORCPT ); Fri, 10 Aug 2018 13:23:04 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:44557 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728374AbeHJRXD (ORCPT ); Fri, 10 Aug 2018 13:23:03 -0400 Received: by mail-wr1-f67.google.com with SMTP id r16-v6so8526412wrt.11 for ; Fri, 10 Aug 2018 07:52:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fDa6F+JrMAbwz8QNQ6MREvsk7u6fmv3IW/3SwDiD83I=; b=Ea8P/LTFFa6AYRg+RuaprWNj/iR6f/cpPyi8WAUaT925QFM0vg32OQGxz3zI7v2/ni 4jkHXgAqcvcaQ8w2NuIgBRMaGke1laRQY8ipQp++5/JAXkPSm+jKr19zQXkx0veuhXzd JI1HviBNCo5nrERkRhIaGtxphJH9pw+GhpeXE= 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; bh=fDa6F+JrMAbwz8QNQ6MREvsk7u6fmv3IW/3SwDiD83I=; b=fRhIptoqi9ajLU+GuA5smxu5jUo1nYa/iQvMPP9RnbgpLfpVEXf1V2izEXqeGnQzTr BoAzOBrHwmaMgZ8TVRxhzj+7fVP1DOm0EPlSHGdHgxq7JO7lsKSAFc0fCC8PSnrtjEfH OkqTGixd3z6PvLGSi9HAMaiGlDSG7rde6zyWIQ2FnUBTGpjZ+EgTYEavaTsIQcMzEu9w 67Tk+HJ8zsXelPI+hny9sFEV7hi6SWDY0pdsxnI5I2Wh8gTh2hZpgpvu9TBpiVhjGYdV g4UFaPyXQI52xIPVk9tvi+v/YW0TWbuBJNSRXA06HYE8Oi8pGkq7sKhvtsACV0SJhJ3a IfCg== X-Gm-Message-State: AOUpUlEwtPf1dmS4jVPwv2+Zlc7OMB9R48FCVj9zFOX5ke1aaq2VJLXW KZUsR2N243xj3c70SkTKniejVQ== X-Google-Smtp-Source: AA+uWPyihDVSqFLmSHsltnp7DcVywhYMERKLrnmQXvwygjcmdH/Ko52MJzAEJahXsTNUVFDBAbCLNQ== X-Received: by 2002:adf:b2f4:: with SMTP id g107-v6mr4664061wrd.53.1533912768351; Fri, 10 Aug 2018 07:52:48 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:47 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 3/8] interconnect: Allow endpoints translation via DT Date: Fri, 10 Aug 2018 17:52:28 +0300 Message-Id: <20180810145233.16466-4-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently we support only platform data for specifying the interconnect endpoints. As now the endpoints are hard-coded into the consumer driver this may lead to complications when a single driver is used by multiple SoCs, which may have different interconnect topology. To avoid cluttering the consumer drivers, introduce a translation function to help us get the board specific interconnect data from device-tree. Signed-off-by: Georgi Djakov Reviewed-by: Evan Green --- drivers/interconnect/core.c | 78 ++++++++++++++++++++++++++++++++++++ include/linux/interconnect.h | 7 ++++ 2 files changed, 85 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 9ca39aca4982..8f874d1b0a0f 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include static DEFINE_IDR(icc_idr); @@ -192,6 +193,83 @@ static int apply_constraints(struct icc_path *path) return ret; } +/** + * of_icc_get() - get a path handle from a DT node based on name + * @dev: device pointer for the consumer device + * @name: interconnect path name + * + * This function will search for a path two endpoints and return an + * icc_path handle on success. Use icc_put() to release constraints when + * they are not needed anymore. + * If the interconnect API is disabled, NULL is returned and the consumer + * drivers will still build. Drivers are free to handle this specifically, + * but they don't have to. NULL is also returned when the "interconnects" + * DT property is missing. + * + * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned + * when the API is disabled or the "interconnects" DT property is missing. + */ +struct icc_path *of_icc_get(struct device *dev, const char *name) +{ + struct device_node *np = NULL; + struct of_phandle_args src_args, dst_args; + u32 src_id, dst_id; + int idx = 0; + int ret; + + if (!dev || !dev->of_node) + return ERR_PTR(-ENODEV); + + np = dev->of_node; + + /* + * When the consumer DT node do not have "interconnects" property + * return a NULL path to skip setting constraints. + */ + if (!of_find_property(np, "interconnects", NULL)) + return NULL; + + /* + * We use a combination of phandle and specifier for endpoint. For now + * lets support only global ids and extend this is the future if needed + * without breaking DT compatibility. + */ + if (name) { + idx = of_property_match_string(np, "interconnect-names", name); + if (idx < 0) + return ERR_PTR(idx); + } + + ret = of_parse_phandle_with_args(np, "interconnects", + "#interconnect-cells", idx * 2, + &src_args); + if (ret) + return ERR_PTR(ret); + + of_node_put(src_args.np); + + if (!src_args.args_count || src_args.args_count > 1) + return ERR_PTR(-EINVAL); + + src_id = src_args.args[0]; + + ret = of_parse_phandle_with_args(np, "interconnects", + "#interconnect-cells", idx * 2 + 1, + &dst_args); + if (ret) + return ERR_PTR(ret); + + of_node_put(dst_args.np); + + if (!dst_args.args_count || dst_args.args_count > 1) + return ERR_PTR(-EINVAL); + + dst_id = dst_args.args[0]; + + return icc_get(dev, src_id, dst_id); +} +EXPORT_SYMBOL_GPL(of_icc_get); + /** * icc_set() - set constraints on an interconnect path between two endpoints * @path: reference to the path returned by icc_get() diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h index 593215371fd6..ae6744da9bc2 100644 --- a/include/linux/interconnect.h +++ b/include/linux/interconnect.h @@ -17,6 +17,7 @@ struct device; struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id); +struct icc_path *of_icc_get(struct device *dev, const char *name); void icc_put(struct icc_path *path); int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw); @@ -28,6 +29,12 @@ static inline struct icc_path *icc_get(struct device *dev, const int src_id, return NULL; } +static inline struct icc_path *of_icc_get(struct device *dev, + const char *name) +{ + return NULL; +} + static inline void icc_put(struct icc_path *path) { } From patchwork Fri Aug 10 14:52:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562789 X-Patchwork-Delegate: agross@codeaurora.org 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 6BA6E1515 for ; Fri, 10 Aug 2018 14:53:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B14F26E78 for ; Fri, 10 Aug 2018 14:53:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F6492B65E; Fri, 10 Aug 2018 14:53:25 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 E056B26E78 for ; Fri, 10 Aug 2018 14:53:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728515AbeHJRXF (ORCPT ); Fri, 10 Aug 2018 13:23:05 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:36999 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728440AbeHJRXE (ORCPT ); Fri, 10 Aug 2018 13:23:04 -0400 Received: by mail-wr1-f66.google.com with SMTP id u12-v6so8556363wrr.4 for ; Fri, 10 Aug 2018 07:52:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=K5qYFSU+P7Ie0HuaSbBHj2ureU4ns5TmNVNvVaDKFEI=; b=Oc9dYoU0IIx5oyfSasJ96vWcCRexjQ9IESwDjDMzi/7iE24sL0+RpUUJPxcQbTnN3l B2B4PriMi1Wy9xWikF3BHBPvxuteu2AZjSMn4zRPuk+chyo9w+42MLzxXpu3M4J8EPb1 bL2C2lDdK9kINRngbQ5J7tppzo/vV+UXjhtZs= 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; bh=K5qYFSU+P7Ie0HuaSbBHj2ureU4ns5TmNVNvVaDKFEI=; b=CVkVgCtENJNl/NNvBLhZHbqsFi29245ZzLwPcWMlJQYzAyJaJCdMiApGM/3bd5ePeb OzbtZ8Sm8Bqoa1be1uyqJQzUSW3Q5tUhZ7LfOMJ4lmohWmoMIUSnfRudH0fyWrbGgF7H kK7gHml+5u/DZBcvAzWvcGGtkNx986NeOuvDf2rCdx6jgn1QKWul1Y6IUonHHzBC0LaF Rxict8d+gCl5ILtXkU4KRRRqRYob5S5Xfe1GfEOLfOQ3OYpI+h0mpq1O5+BvN3BZtbJG bAEzlTrQuYV5RplgD9hpyrnSpHrJaoItEweBwfnMPufaZ4kEOFyMja3HqFvV22LcK3jU jV/A== X-Gm-Message-State: AOUpUlFZivaFjBeZC0nyvcIZTLxM+aU8Tr/DAhRpJbS3LRrnJS617jMj lcMUaOd2d+tE8JPtchYjtZsH8g== X-Google-Smtp-Source: AA+uWPwPG8JZ+uwAWaTA8PKaZNn8IrBRdx89DB5+g4frnXUbq5xamKzC9FnnF+Tii1bC5h5aYOwzTA== X-Received: by 2002:adf:adc9:: with SMTP id w67-v6mr4382476wrc.135.1533912770222; Fri, 10 Aug 2018 07:52:50 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:49 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 4/8] interconnect: Add debugfs support Date: Fri, 10 Aug 2018 17:52:29 +0300 Message-Id: <20180810145233.16466-5-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add a functionality to provide information about the current constraints per each node and provider. Signed-off-by: Georgi Djakov Reviewed-by: Evan Green --- drivers/interconnect/core.c | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 8f874d1b0a0f..288ef83c3bc0 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -6,6 +6,7 @@ * Author: Georgi Djakov */ +#include #include #include #include @@ -17,10 +18,12 @@ #include #include #include +#include static DEFINE_IDR(icc_idr); static LIST_HEAD(icc_provider_list); static DEFINE_MUTEX(icc_lock); +static struct dentry *icc_debugfs_dir; /** * struct icc_req - constraints that are attached to each node @@ -49,6 +52,62 @@ struct icc_path { struct icc_req reqs[]; }; +#ifdef CONFIG_DEBUG_FS + +static void icc_summary_show_one(struct seq_file *s, struct icc_node *n) +{ + if (!n) + return; + + seq_printf(s, "%-30s %12d %12d\n", + n->name, n->avg_bw, n->peak_bw); +} + +static int icc_summary_show(struct seq_file *s, void *data) +{ + struct icc_provider *provider; + + seq_puts(s, " node avg peak\n"); + seq_puts(s, "--------------------------------------------------------\n"); + + mutex_lock(&icc_lock); + + list_for_each_entry(provider, &icc_provider_list, provider_list) { + struct icc_node *n; + + list_for_each_entry(n, &provider->nodes, node_list) { + struct icc_req *r; + + icc_summary_show_one(s, n); + hlist_for_each_entry(r, &n->req_list, req_node) { + if (!r->dev) + continue; + + seq_printf(s, " %-26s %12d %12d\n", + dev_name(r->dev), r->avg_bw, + r->peak_bw); + } + } + } + + mutex_unlock(&icc_lock); + + return 0; +} + +static int icc_summary_open(struct inode *inode, struct file *file) +{ + return single_open(file, icc_summary_show, inode->i_private); +} + +static const struct file_operations icc_summary_fops = { + .open = icc_summary_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + static struct icc_node *node_find(const int id) { return idr_find(&icc_idr, id); @@ -646,6 +705,25 @@ int icc_provider_del(struct icc_provider *provider) } EXPORT_SYMBOL_GPL(icc_provider_del); +static int __init icc_init(void) +{ +#ifdef CONFIG_DEBUG_FS + icc_debugfs_dir = debugfs_create_dir("interconnect", NULL); + debugfs_create_file("interconnect_summary", 0444, + icc_debugfs_dir, NULL, &icc_summary_fops); +#endif + return 0; +} + +static void __exit icc_exit(void) +{ +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(icc_debugfs_dir); +#endif +} +module_init(icc_init); +module_exit(icc_exit); + MODULE_AUTHOR("Georgi Djakov X-Patchwork-Id: 10562787 X-Patchwork-Delegate: agross@codeaurora.org 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 9A0BA174A for ; Fri, 10 Aug 2018 14:53:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 88CFC26E78 for ; Fri, 10 Aug 2018 14:53:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7AB972B65E; Fri, 10 Aug 2018 14:53:22 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable 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 E96F426E78 for ; Fri, 10 Aug 2018 14:53:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728603AbeHJRXH (ORCPT ); Fri, 10 Aug 2018 13:23:07 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:46530 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728565AbeHJRXH (ORCPT ); Fri, 10 Aug 2018 13:23:07 -0400 Received: by mail-wr1-f66.google.com with SMTP id h14-v6so8531100wrw.13 for ; Fri, 10 Aug 2018 07:52:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=1jM7ZXItlRq3zbhWV6TmYrbuDhKvEvpgy6vWixlAq2M=; b=bd0/zAHleQ+UoEgVy6lFTYFaqe5/8Xab+pkrP+rEnpg0qUct15joy45s0zRNMJ/3dM r5TYr4YDO9r9GmVDuJkY2Cl0KWQkGO+UMAxHkUfA92Wid2YSHN3rO6mj/bvkZYKQfPXq ou2i1H9gde03HYnDS6uAooJbips+A/n5+JsZ4= 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; bh=1jM7ZXItlRq3zbhWV6TmYrbuDhKvEvpgy6vWixlAq2M=; b=qDFyOaHkmvja3nlbLvJhvMnZ7H132alwX1XhBQWtXF80/ajP7yc4fH5NBSPQf/AOQS GNv1oSVnvhmrSF8V/Pu4ezEk64MPXEDnM1CohVQwd2XQ8j0TQuDiNnaJFS7hwiLAolLs nx7/yzKPcHRHnczKKWY0ueHYs55oi76OjvLizYMIRvG5PIDFNMXcU4zyONsQEf4mmbT8 zM4SCdIPtaLhLXfZacGap4DBKmuIt68ga1z1Sjxr2wpi2xnZhDMEicg/5pkQeWef0eJf m2mJYvawpqs0fuLLQWiPjG8dG7Yk4l4BU3i0OJOMPitBErPFiv0Nqd6LYIg5lUhSBNqR bNrQ== X-Gm-Message-State: AOUpUlEGd6qctjgM4M+5gJl8fIJHVZfLUJoSf+I3cBxoituuz7q6LiHl dBu5RXnOqLgEeUsqznNqJ7ITJw== X-Google-Smtp-Source: AA+uWPw8TJOFpTSbXxDt676MjuVsc14qBtrNwPXnXDi0tZnQz6jUnVkCTkCbvKkl/GWgPY62pYkYEA== X-Received: by 2002:adf:ff49:: with SMTP id u9-v6mr4807099wrs.15.1533912772266; Fri, 10 Aug 2018 07:52:52 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:51 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 5/8] interconnect: qcom: Add RPM communication Date: Fri, 10 Aug 2018 17:52:30 +0300 Message-Id: <20180810145233.16466-6-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On some Qualcomm SoCs, there is a remote processor, which controls some of the Network-On-Chip interconnect resources. Other CPUs express their needs by communicating with this processor. Add a driver to handle communication with this remote processor. Signed-off-by: Georgi Djakov Reviewed-by: Evan Green --- .../bindings/interconnect/qcom-smd.txt | 32 +++++++ drivers/interconnect/qcom/Kconfig | 14 +++ drivers/interconnect/qcom/Makefile | 2 + drivers/interconnect/qcom/smd-rpm.c | 91 +++++++++++++++++++ drivers/interconnect/qcom/smd-rpm.h | 16 ++++ 5 files changed, 155 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom-smd.txt create mode 100644 drivers/interconnect/qcom/Kconfig create mode 100644 drivers/interconnect/qcom/Makefile create mode 100644 drivers/interconnect/qcom/smd-rpm.c create mode 100644 drivers/interconnect/qcom/smd-rpm.h diff --git a/Documentation/devicetree/bindings/interconnect/qcom-smd.txt b/Documentation/devicetree/bindings/interconnect/qcom-smd.txt new file mode 100644 index 000000000000..2325167f6eaf --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom-smd.txt @@ -0,0 +1,32 @@ +Qualcomm SMD-RPM interconnect driver binding +------------------------------------------------ +The RPM (Resource Power Manager) is a dedicated hardware engine +for managing the shared SoC resources in order to keep the lowest +power profile. It communicates with other hardware subsystems via +the shared memory driver (SMD) back-end and accepts requests for +various resources. + +Required properties : +- compatible : shall contain only one of the following: + "qcom,interconnect-smd-rpm" + +Example: + smd { + compatible = "qcom,smd"; + + rpm { + interrupts = ; + qcom,ipc = <&apcs 8 0>; + qcom,smd-edge = <15>; + + rpm_requests { + compatible = "qcom,rpm-msm8916"; + qcom,smd-channels = "rpm_requests"; + + interconnect-smd-rpm { + compatible = "qcom,interconnect-smd-rpm"; + }; + + }; + }; + }; diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig new file mode 100644 index 000000000000..812e9464765a --- /dev/null +++ b/drivers/interconnect/qcom/Kconfig @@ -0,0 +1,14 @@ +config INTERCONNECT_QCOM + bool "Qualcomm Network-on-Chip interconnect drivers" + depends on INTERCONNECT + depends on ARCH_QCOM || COMPILE_TEST + help + Support for Qualcomm's Network-on-Chip interconnect hardware. + +config INTERCONNECT_QCOM_SMD_RPM + tristate "Qualcomm SMD RPM interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + help + This is a driver for communicating interconnect related configuration + details with a remote processor (RPM) on Qualcomm platforms. diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile new file mode 100644 index 000000000000..5b65e4011b59 --- /dev/null +++ b/drivers/interconnect/qcom/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += smd-rpm.o diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c new file mode 100644 index 000000000000..48b7a2a6eb84 --- /dev/null +++ b/drivers/interconnect/qcom/smd-rpm.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RPM over SMD communication wrapper for interconnects + * + * Copyright (C) 2018 Linaro Ltd + * Author: Georgi Djakov + */ + +#include +#include +#include +#include +#include +#include +#include "smd-rpm.h" + +#define RPM_KEY_BW 0x00007762 + +static struct qcom_icc_rpm { + struct qcom_smd_rpm *rpm; +} icc_rpm_smd; + +struct icc_rpm_smd_req { + __le32 key; + __le32 nbytes; + __le32 value; +}; + +bool qcom_icc_rpm_smd_available(void) +{ + if (!icc_rpm_smd.rpm) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_available); + +int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val) +{ + struct icc_rpm_smd_req req = { + .key = cpu_to_le32(RPM_KEY_BW), + .nbytes = cpu_to_le32(sizeof(u32)), + .value = cpu_to_le32(val), + }; + + return qcom_rpm_smd_write(icc_rpm_smd.rpm, ctx, rsc_type, id, &req, + sizeof(req)); +} +EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_send); + +static int qcom_icc_rpm_smd_probe(struct platform_device *pdev) +{ + icc_rpm_smd.rpm = dev_get_drvdata(pdev->dev.parent); + if (!icc_rpm_smd.rpm) { + dev_err(&pdev->dev, "unable to retrieve handle to RPM\n"); + return -ENODEV; + } + + return 0; +} + +static const struct of_device_id qcom_icc_rpm_smd_dt_match[] = { + { .compatible = "qcom,interconnect-smd-rpm", }, + { }, +}; + +MODULE_DEVICE_TABLE(of, qcom_icc_rpm_smd_dt_match); + +static struct platform_driver qcom_interconnect_rpm_smd_driver = { + .driver = { + .name = "qcom-interconnect-smd-rpm", + .of_match_table = qcom_icc_rpm_smd_dt_match, + }, + .probe = qcom_icc_rpm_smd_probe, +}; + +static int __init rpm_smd_interconnect_init(void) +{ + return platform_driver_register(&qcom_interconnect_rpm_smd_driver); +} +subsys_initcall(rpm_smd_interconnect_init); + +static void __exit rpm_smd_interconnect_exit(void) +{ + platform_driver_unregister(&qcom_interconnect_rpm_smd_driver); +} +module_exit(rpm_smd_interconnect_exit) + +MODULE_AUTHOR("Georgi Djakov "); +MODULE_DESCRIPTION("Qualcomm SMD RPM interconnect driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/smd-rpm.h b/drivers/interconnect/qcom/smd-rpm.h new file mode 100644 index 000000000000..3b1c347475ff --- /dev/null +++ b/drivers/interconnect/qcom/smd-rpm.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H +#define __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H + + +#include + +bool qcom_icc_rpm_smd_available(void); +int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val); + +#endif From patchwork Fri Aug 10 14:52:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562771 X-Patchwork-Delegate: agross@codeaurora.org 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 AE2A5174A for ; Fri, 10 Aug 2018 14:52:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9993626E78 for ; Fri, 10 Aug 2018 14:52:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8CE9C27FA9; Fri, 10 Aug 2018 14:52:59 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable 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 1959C280CF for ; Fri, 10 Aug 2018 14:52:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728821AbeHJRXK (ORCPT ); Fri, 10 Aug 2018 13:23:10 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:41964 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728599AbeHJRXJ (ORCPT ); Fri, 10 Aug 2018 13:23:09 -0400 Received: by mail-wr1-f65.google.com with SMTP id j5-v6so8539977wrr.8 for ; Fri, 10 Aug 2018 07:52:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9oUIEusk495SIX9kXu/WUGAbH7L0f6JAltllXHNc7ks=; b=fDe9hhytJG0RF8rhbn+47nA7nVGZgSi5GoxHmDWZ/FDIp3LmfvcWtFr3eeYpffMVsx txJ91+MXpGjCAjUDBTJcZDikUD9hUWJbUzVFMe2UpXWFNt+TQ+fZPtTPKy8VQ1u7xhYZ SDGvN868w6X6yEhGEWaiHRIhLWtVffvPCYGH4= 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; bh=9oUIEusk495SIX9kXu/WUGAbH7L0f6JAltllXHNc7ks=; b=A7+53ZdQQFebS5TygzuO2IK4sGsj8gkm67N9bIofTVSIYy+3TFppvsqsZBlSQJ4Gsf emh/JNX4AfUZd2oYcjJIwmYW3PI5jNL+y6UVZAp3rgMAQng1wol8LnDnGckSIt4VF2vT ictgxXsPpipNywtD1kx39F2H5UofzpaIkLa37OmAyohnfdW1ee50Xkz4tC9laeGSlsiQ aNrH7E6LX9zWmMN9Ji5CXRUcEsuXzQ/dR6nPyJYtXEd6ZOVMrO6QDQEJYe/F5WW4wTmc qc0wRuro0Sl0uvYrENX6MI64gjnicl5BtqTFNX6rkF9Pj8UFw4wq/PH4hA5pIRqaUidl 4q1Q== X-Gm-Message-State: AOUpUlEig36pKj4kxGTP482ELdgmKDdxOTBG908KBy9Fw/MWA3lTP70i PSoemrY5r8/A8KC49+PR545ynA== X-Google-Smtp-Source: AA+uWPzAPOdHjNzoH6V5FoF5kVMv1FPsMN8GACN1uXMivfEOeFE3M28lKi12tULvW2kju7pOPV1e4w== X-Received: by 2002:adf:820a:: with SMTP id 10-v6mr4395879wrb.144.1533912774010; Fri, 10 Aug 2018 07:52:54 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:53 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 6/8] dt-bindings: interconnect: Document qcom,msm8916 NoC bindings Date: Fri, 10 Aug 2018 17:52:31 +0300 Message-Id: <20180810145233.16466-7-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Document the device-tree bindings of the Network-On-Chip interconnect hardware found on Qualcomm msm8916 platforms. Signed-off-by: Georgi Djakov Reviewed-by: Evan Green --- .../bindings/interconnect/qcom-msm8916.txt | 41 ++++++++ include/dt-bindings/interconnect/qcom.h | 98 +++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom-msm8916.txt create mode 100644 include/dt-bindings/interconnect/qcom.h diff --git a/Documentation/devicetree/bindings/interconnect/qcom-msm8916.txt b/Documentation/devicetree/bindings/interconnect/qcom-msm8916.txt new file mode 100644 index 000000000000..744df51df4ed --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom-msm8916.txt @@ -0,0 +1,41 @@ +Qualcomm MSM8916 Network-On-Chip interconnect driver binding +---------------------------------------------------- + +Required properties : +- compatible : shall contain only one of the following: + "qcom,msm8916-bimc" + "qcom,msm8916-pnoc" + "qcom,msm8916-snoc" +- #interconnect-cells : should contain 1 +- reg : shall contain base register location and length + +Optional properties : +clocks : list of phandles and specifiers to all interconnect bus clocks +clock-names : clock names should include both "bus_clk" and "bus_a_clk" + +Examples: + + snoc: snoc@580000 { + compatible = "qcom,msm8916-snoc"; + #interconnect-cells = <1>; + reg = <0x580000 0x14000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + }; + bimc: bimc@400000 { + compatible = "qcom,msm8916-bimc"; + #interconnect-cells = <1>; + reg = <0x400000 0x62000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + }; + pnoc: pnoc@500000 { + compatible = "qcom,msm8916-pnoc"; + #interconnect-cells = <1>; + reg = <0x500000 0x11000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + }; diff --git a/include/dt-bindings/interconnect/qcom.h b/include/dt-bindings/interconnect/qcom.h new file mode 100644 index 000000000000..f4d154f0afbf --- /dev/null +++ b/include/dt-bindings/interconnect/qcom.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm interconnect IDs + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_H + +#define BIMC_SNOC_MAS 0 +#define BIMC_SNOC_SLV 1 +#define MASTER_AMPSS_M0 2 +#define MASTER_BLSP_1 3 +#define MASTER_CRYPTO_CORE0 4 +#define MASTER_DEHR 5 +#define MASTER_GRAPHICS_3D 6 +#define MASTER_JPEG 7 +#define MASTER_LPASS 8 +#define MASTER_MDP_PORT0 9 +#define MASTER_QDSS_BAM 10 +#define MASTER_QDSS_ETR 11 +#define MASTER_SDCC_1 12 +#define MASTER_SDCC_2 13 +#define MASTER_SNOC_CFG 14 +#define MASTER_SPDM 15 +#define MASTER_TCU_0 16 +#define MASTER_TCU_1 17 +#define MASTER_USB_HS 18 +#define MASTER_VFE 19 +#define MASTER_VIDEO_P0 20 +#define PNOC_INT_0 21 +#define PNOC_INT_1 22 +#define PNOC_M_0 23 +#define PNOC_M_1 24 +#define PNOC_SLV_0 25 +#define PNOC_SLV_1 26 +#define PNOC_SLV_2 27 +#define PNOC_SLV_3 28 +#define PNOC_SLV_4 29 +#define PNOC_SLV_8 30 +#define PNOC_SLV_9 31 +#define PNOC_SNOC_MAS 32 +#define PNOC_SNOC_SLV 33 +#define SLAVE_AMPSS_L2 34 +#define SLAVE_BIMC_CFG 35 +#define SLAVE_BLSP_1 36 +#define SLAVE_BOOT_ROM 37 +#define SLAVE_CAMERA_CFG 38 +#define SLAVE_CATS_128 39 +#define SLAVE_CLK_CTL 40 +#define SLAVE_CRYPTO_0_CFG 41 +#define SLAVE_DEHR_CFG 42 +#define SLAVE_DISPLAY_CFG 43 +#define SLAVE_EBI_CH0 44 +#define SLAVE_GRAPHICS_3D_CFG 45 +#define SLAVE_IMEM_CFG 46 +#define SLAVE_LPASS 47 +#define SLAVE_MPM 48 +#define SLAVE_MSM_PDM 49 +#define SLAVE_MSM_TCSR 50 +#define SLAVE_MSS 51 +#define SLAVE_OCMEM_64 52 +#define SLAVE_PMIC_ARB 53 +#define SLAVE_PNOC_CFG 54 +#define SLAVE_PRNG 55 +#define SLAVE_QDSS_CFG 56 +#define SLAVE_QDSS_STM 57 +#define SLAVE_RBCPR_CFG 58 +#define SLAVE_RPM_MSG_RAM 59 +#define SLAVE_SDCC_1 60 +#define SLAVE_SDCC_4 61 +#define SLAVE_SECURITY 62 +#define SLAVE_SERVICE_SNOC 63 +#define SLAVE_SNOC_CFG 64 +#define SLAVE_SPDM 65 +#define SLAVE_SYSTEM_IMEM 66 +#define SLAVE_TLMM 67 +#define SLAVE_USB_HS 68 +#define SLAVE_VENUS_CFG 69 +#define SNOC_BIMC_0_MAS 70 +#define SNOC_BIMC_0_SLV 71 +#define SNOC_BIMC_1_MAS 72 +#define SNOC_BIMC_1_SLV 73 +#define SNOC_INT_0 74 +#define SNOC_INT_1 75 +#define SNOC_INT_BIMC 76 +#define SNOC_MM_INT_0 77 +#define SNOC_MM_INT_1 78 +#define SNOC_MM_INT_2 79 +#define SNOC_MM_INT_BIMC 80 +#define SNOC_PNOC_MAS 81 +#define SNOC_PNOC_SLV 82 +#define SNOC_QDSS_INT 83 +#define SYSTEM_SLAVE_FAB_APPS 84 + +#endif From patchwork Fri Aug 10 14:52:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562773 X-Patchwork-Delegate: agross@codeaurora.org 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 E735213BB for ; Fri, 10 Aug 2018 14:53:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D452726E78 for ; Fri, 10 Aug 2018 14:53:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C7D1A280CF; Fri, 10 Aug 2018 14:53:01 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 793EC26E78 for ; Fri, 10 Aug 2018 14:53:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728843AbeHJRXL (ORCPT ); Fri, 10 Aug 2018 13:23:11 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42602 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728787AbeHJRXL (ORCPT ); Fri, 10 Aug 2018 13:23:11 -0400 Received: by mail-wr1-f65.google.com with SMTP id e7-v6so8533484wrs.9 for ; Fri, 10 Aug 2018 07:52:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rZRlk0QLupANUg+kUBYnjCYKyp6SOrq+JSOHOXc+qcQ=; b=OyOTQBvir/jSPnLd0xMNdMlB3c3W5miI6HJUwFF+Hqsphcck3fnUY3tD26aVrXusDZ NLIzejEdcAflPkvX1q7JkpGzdYrHz8j9kdRZ969whSjEMsYB4QPbkGQ5eax0EvmPf5uT 9JWvY7/Fjf4sf8hiODq+S1jfsRGq39jdaNI1g= 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; bh=rZRlk0QLupANUg+kUBYnjCYKyp6SOrq+JSOHOXc+qcQ=; b=gKYTYHtaPCJQC0jEp3tzIqyALfQHSwYpglPYXbK7PJmQ3E/VVtS0q9+m38eM49h774 5NEmh2BcqL0J/rIJyOCXiDw8nNuikXCC7X1d+RfYj710GTaoY3t96m92raXEZftxSgpe 8vb86QzHc2vXSoD8dCX00YXOV8+7ue6yCzVXCmlSDtEqgKdVV51tCE3JhwsEXr9FVFjl VzpcVxvmLHZVSiozg9Qti1VuqbtzOjutulPBvCqkuFV10HHKOfZRgTme6BqEBZOg9g4e kWHiOImyM2zkgtJQqK/Ica0ehyOZFGGN0MM+46xzQ58sC9smxke/XgH18D+7eHRXx1Fp Ja4w== X-Gm-Message-State: AOUpUlE1HHR/EPyHS2EFQ93BEMsBxIFNqAjhL91aeDfa0IxRTO0UuTtd IB+5LPKCa/o0oeWZczkj9zbQuw== X-Google-Smtp-Source: AA+uWPzEOWRNLhfMbMFwgO54gwwiBzO/jFvAMdhrfLm/8EUkAhI5KImGO6FX6bVlHJiosbuQczjZ/Q== X-Received: by 2002:adf:bf10:: with SMTP id p16-v6mr4324762wrh.235.1533912775901; Fri, 10 Aug 2018 07:52:55 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:55 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 7/8] interconnect: qcom: Add msm8916 interconnect provider driver Date: Fri, 10 Aug 2018 17:52:32 +0300 Message-Id: <20180810145233.16466-8-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add driver for the Qualcomm interconnect buses found in msm8916 based platforms. Signed-off-by: Georgi Djakov --- drivers/interconnect/Kconfig | 5 + drivers/interconnect/Makefile | 1 + drivers/interconnect/qcom/Kconfig | 9 + drivers/interconnect/qcom/Makefile | 2 + drivers/interconnect/qcom/msm8916.c | 510 ++++++++++++++++++++++++++++ 5 files changed, 527 insertions(+) create mode 100644 drivers/interconnect/qcom/msm8916.c diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig index a261c7d41deb..07a8276fa35a 100644 --- a/drivers/interconnect/Kconfig +++ b/drivers/interconnect/Kconfig @@ -8,3 +8,8 @@ menuconfig INTERCONNECT If unsure, say no. +if INTERCONNECT + +source "drivers/interconnect/qcom/Kconfig" + +endif diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index 97fca2e09d24..7944cbca0527 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_INTERCONNECT) += core.o +obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 812e9464765a..add6d7e1e24e 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -12,3 +12,12 @@ config INTERCONNECT_QCOM_SMD_RPM help This is a driver for communicating interconnect related configuration details with a remote processor (RPM) on Qualcomm platforms. + +config INTERCONNECT_QCOM_MSM8916 + tristate "Qualcomm MSM8916 interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + select INTERCONNECT_QCOM_SMD_RPM + help + This is a driver for the Qualcomm Network-on-Chip on msm8916-based + platforms. diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index 5b65e4011b59..53f3380277f6 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -1,2 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += smd-rpm.o + +obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += msm8916.o diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c new file mode 100644 index 000000000000..74145f4f74f1 --- /dev/null +++ b/drivers/interconnect/qcom/msm8916.c @@ -0,0 +1,510 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Linaro Ltd + * Author: Georgi Djakov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smd-rpm.h" + +#define RPM_BUS_MASTER_REQ 0x73616d62 +#define RPM_BUS_SLAVE_REQ 0x766c7362 + +#define to_qcom_provider(_provider) \ + container_of(_provider, struct qcom_icc_provider, provider) + +enum qcom_qos_mode { + QCOM_QOS_MODE_BYPASS = 0, + QCOM_QOS_MODE_FIXED, + QCOM_QOS_MODE_MAX, +}; + +struct qcom_icc_provider { + struct icc_provider provider; + void __iomem *base; + struct clk *bus_clk; + struct clk *bus_a_clk; +}; + +#define MSM8916_MAX_LINKS 8 + +/** + * struct qcom_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 + * @port: the offset index into the masters QoS register space + * @buswidth: width of the interconnect between a node and the bus (bytes) + * @ap_owned: the AP CPU does the writing to QoS registers + * @qos_mode: QoS mode for ap_owned resources + * @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 qcom_icc_node { + unsigned char *name; + u16 id; + u16 links[MSM8916_MAX_LINKS]; + u16 num_links; + u16 port; + u16 buswidth; + bool ap_owned; + enum qcom_qos_mode qos_mode; + int mas_rpm_id; + int slv_rpm_id; + u64 rate; +}; + +struct qcom_icc_desc { + struct qcom_icc_node **nodes; + size_t num_nodes; +}; + +#define DEFINE_QNODE(_name, _id, _port, _buswidth, _ap_owned, \ + _mas_rpm_id, _slv_rpm_id, _qos_mode, \ + _numlinks, ...) \ + static struct qcom_icc_node _name = { \ + .name = #_name, \ + .id = _id, \ + .port = _port, \ + .buswidth = _buswidth, \ + .ap_owned = _ap_owned, \ + .mas_rpm_id = _mas_rpm_id, \ + .slv_rpm_id = _slv_rpm_id, \ + .qos_mode = _qos_mode, \ + .num_links = _numlinks, \ + .links = { __VA_ARGS__ }, \ + } + +DEFINE_QNODE(bimc_snoc_mas, BIMC_SNOC_MAS, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, BIMC_SNOC_SLV); +DEFINE_QNODE(bimc_snoc_slv, BIMC_SNOC_SLV, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 2, SNOC_INT_0, SNOC_INT_1); +DEFINE_QNODE(mas_apss, MASTER_AMPSS_M0, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_EBI_CH0, BIMC_SNOC_MAS, SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_audio, MASTER_LPASS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_M_0); +DEFINE_QNODE(mas_blsp_1, MASTER_BLSP_1, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_M_1); +DEFINE_QNODE(mas_dehr, MASTER_DEHR, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_M_0); +DEFINE_QNODE(mas_gfx, MASTER_GRAPHICS_3D, 2, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_EBI_CH0, BIMC_SNOC_MAS, SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_jpeg, MASTER_JPEG, 6, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, SNOC_MM_INT_0, SNOC_MM_INT_2); +DEFINE_QNODE(mas_mdp, MASTER_MDP_PORT0, 7, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, SNOC_MM_INT_0, SNOC_MM_INT_2); +DEFINE_QNODE(mas_pnoc_crypto_0, MASTER_CRYPTO_CORE0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_INT_1); +DEFINE_QNODE(mas_pnoc_sdcc_1, MASTER_SDCC_1, 7, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_INT_1); +DEFINE_QNODE(mas_pnoc_sdcc_2, MASTER_SDCC_2, 8, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_INT_1); +DEFINE_QNODE(mas_qdss_bam, MASTER_QDSS_BAM, 11, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_QDSS_INT); +DEFINE_QNODE(mas_qdss_etr, MASTER_QDSS_ETR, 10, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_QDSS_INT); +DEFINE_QNODE(mas_snoc_cfg, MASTER_SNOC_CFG, 0, 16, 0, 20, -1, QCOM_QOS_MODE_BYPASS, 1, SNOC_QDSS_INT); +DEFINE_QNODE(mas_spdm, MASTER_SPDM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_M_0); +DEFINE_QNODE(mas_tcu0, MASTER_TCU_0, 5, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_EBI_CH0, BIMC_SNOC_MAS, SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_tcu1, MASTER_TCU_1, 6, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_EBI_CH0, BIMC_SNOC_MAS, SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_usb_hs, MASTER_USB_HS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_M_1); +DEFINE_QNODE(mas_vfe, MASTER_VFE, 9, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, SNOC_MM_INT_1, SNOC_MM_INT_2); +DEFINE_QNODE(mas_video, MASTER_VIDEO_P0, 8, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, SNOC_MM_INT_0, SNOC_MM_INT_2); +DEFINE_QNODE(mm_int_0, SNOC_MM_INT_0, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_MM_INT_BIMC); +DEFINE_QNODE(mm_int_1, SNOC_MM_INT_1, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_MM_INT_BIMC); +DEFINE_QNODE(mm_int_2, SNOC_MM_INT_2, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_INT_0); +DEFINE_QNODE(mm_int_bimc, SNOC_MM_INT_BIMC, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_BIMC_1_MAS); +DEFINE_QNODE(pnoc_int_0, PNOC_INT_0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 8, PNOC_SNOC_MAS, PNOC_SLV_0, PNOC_SLV_1, PNOC_SLV_2, PNOC_SLV_3, PNOC_SLV_4, PNOC_SLV_8, PNOC_SLV_9); +DEFINE_QNODE(pnoc_int_1, PNOC_INT_1, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_SNOC_MAS); +DEFINE_QNODE(pnoc_m_0, PNOC_M_0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_INT_0); +DEFINE_QNODE(pnoc_m_1, PNOC_M_1, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_SNOC_MAS); +DEFINE_QNODE(pnoc_s_0, PNOC_SLV_0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, SLAVE_CLK_CTL, SLAVE_TLMM, SLAVE_MSM_TCSR, SLAVE_SECURITY, SLAVE_MSS); +DEFINE_QNODE(pnoc_s_1, PNOC_SLV_1, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, SLAVE_IMEM_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_RPM_MSG_RAM, SLAVE_MSM_PDM, SLAVE_PRNG); +DEFINE_QNODE(pnoc_s_2, PNOC_SLV_2, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, SLAVE_SPDM, SLAVE_BOOT_ROM, SLAVE_BIMC_CFG, SLAVE_PNOC_CFG, SLAVE_PMIC_ARB); +DEFINE_QNODE(pnoc_s_3, PNOC_SLV_3, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, SLAVE_MPM, SLAVE_SNOC_CFG, SLAVE_RBCPR_CFG, SLAVE_QDSS_CFG, SLAVE_DEHR_CFG); +DEFINE_QNODE(pnoc_s_4, PNOC_SLV_4, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_VENUS_CFG, SLAVE_CAMERA_CFG, SLAVE_DISPLAY_CFG); +DEFINE_QNODE(pnoc_s_8, PNOC_SLV_8, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_USB_HS, SLAVE_SDCC_1, SLAVE_BLSP_1); +DEFINE_QNODE(pnoc_s_9, PNOC_SLV_9, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 3, SLAVE_SDCC_4, SLAVE_LPASS, SLAVE_GRAPHICS_3D_CFG); +DEFINE_QNODE(pnoc_snoc_mas, PNOC_SNOC_MAS, 0, 8, 0, 29, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_SNOC_SLV); +DEFINE_QNODE(pnoc_snoc_slv, PNOC_SNOC_SLV, 0, 8, 0, -1, 45, QCOM_QOS_MODE_FIXED, 3, SNOC_INT_0, SNOC_INT_BIMC, SNOC_INT_1); +DEFINE_QNODE(qdss_int, SNOC_QDSS_INT, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 2, SNOC_INT_0, SNOC_INT_BIMC); +DEFINE_QNODE(slv_apps_l2, SLAVE_AMPSS_L2, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_apss, SYSTEM_SLAVE_FAB_APPS, 0, 4, 0, -1, 20, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_audio, SLAVE_LPASS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_bimc_cfg, SLAVE_BIMC_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_blsp_1, SLAVE_BLSP_1, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_boot_rom, SLAVE_BOOT_ROM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_camera_cfg, SLAVE_CAMERA_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_cats_0, SLAVE_CATS_128, 0, 16, 0, -1, 106, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_cats_1, SLAVE_OCMEM_64, 0, 8, 0, -1, 107, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_clk_ctl, SLAVE_CLK_CTL, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_crypto_0_cfg, SLAVE_CRYPTO_0_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_dehr_cfg, SLAVE_DEHR_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_display_cfg, SLAVE_DISPLAY_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_ebi_ch0, SLAVE_EBI_CH0, 0, 8, 0, -1, 0, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_gfx_cfg, SLAVE_GRAPHICS_3D_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_imem_cfg, SLAVE_IMEM_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_imem, SLAVE_SYSTEM_IMEM, 0, 8, 0, -1, 26, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_mpm, SLAVE_MPM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_msg_ram, SLAVE_RPM_MSG_RAM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_mss, SLAVE_MSS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_pdm, SLAVE_MSM_PDM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_pmic_arb, SLAVE_PMIC_ARB, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_pnoc_cfg, SLAVE_PNOC_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_prng, SLAVE_PRNG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_qdss_cfg, SLAVE_QDSS_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_qdss_stm, SLAVE_QDSS_STM, 0, 4, 0, -1, 30, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_rbcpr_cfg, SLAVE_RBCPR_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_sdcc_1, SLAVE_SDCC_1, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_sdcc_2, SLAVE_SDCC_4, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_security, SLAVE_SECURITY, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_snoc_cfg, SLAVE_SNOC_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_spdm, SLAVE_SPDM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_srvc_snoc, SLAVE_SERVICE_SNOC, 0, 8, 0, -1, 29, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_tcsr, SLAVE_MSM_TCSR, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_tlmm, SLAVE_TLMM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_usb_hs, SLAVE_USB_HS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_venus_cfg, SLAVE_VENUS_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(snoc_bimc_0_mas, SNOC_BIMC_0_MAS, 0, 8, 0, 3, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_BIMC_0_SLV); +DEFINE_QNODE(snoc_bimc_0_slv, SNOC_BIMC_0_SLV, 0, 8, 0, -1, 24, QCOM_QOS_MODE_FIXED, 1, SLAVE_EBI_CH0); +DEFINE_QNODE(snoc_bimc_1_mas, SNOC_BIMC_1_MAS, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_BIMC_1_SLV); +DEFINE_QNODE(snoc_bimc_1_slv, SNOC_BIMC_1_SLV, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, SLAVE_EBI_CH0); +DEFINE_QNODE(snoc_int_0, SNOC_INT_0, 0, 8, 0, 99, 130, QCOM_QOS_MODE_FIXED, 3, SLAVE_QDSS_STM, SLAVE_SYSTEM_IMEM, SNOC_PNOC_MAS); +DEFINE_QNODE(snoc_int_1, SNOC_INT_1, 0, 8, 0, 100, 131, QCOM_QOS_MODE_FIXED, 3, SYSTEM_SLAVE_FAB_APPS, SLAVE_CATS_128, SLAVE_OCMEM_64); +DEFINE_QNODE(snoc_int_bimc, SNOC_INT_BIMC, 0, 8, 0, 101, 132, QCOM_QOS_MODE_FIXED, 1, SNOC_BIMC_0_MAS); +DEFINE_QNODE(snoc_pnoc_mas, SNOC_PNOC_MAS, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, SNOC_PNOC_SLV); +DEFINE_QNODE(snoc_pnoc_slv, SNOC_PNOC_SLV, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, PNOC_INT_0); + +static struct qcom_icc_node *msm8916_snoc_nodes[] = { + &bimc_snoc_slv, + &mas_jpeg, + &mas_mdp, + &mas_qdss_bam, + &mas_qdss_etr, + &mas_snoc_cfg, + &mas_vfe, + &mas_video, + &mm_int_0, + &mm_int_1, + &mm_int_2, + &mm_int_bimc, + &pnoc_snoc_slv, + &qdss_int, + &slv_apss, + &slv_cats_0, + &slv_cats_1, + &slv_imem, + &slv_qdss_stm, + &slv_srvc_snoc, + &snoc_bimc_0_mas, + &snoc_bimc_1_mas, + &snoc_int_0, + &snoc_int_1, + &snoc_int_bimc, + &snoc_pnoc_mas, +}; + +static struct qcom_icc_desc msm8916_snoc = { + .nodes = msm8916_snoc_nodes, + .num_nodes = ARRAY_SIZE(msm8916_snoc_nodes), +}; + +static struct qcom_icc_node *msm8916_bimc_nodes[] = { + &bimc_snoc_mas, + &mas_apss, + &mas_gfx, + &mas_tcu0, + &mas_tcu1, + &slv_apps_l2, + &slv_ebi_ch0, + &snoc_bimc_0_slv, + &snoc_bimc_1_slv, +}; + +static struct qcom_icc_desc msm8916_bimc = { + .nodes = msm8916_bimc_nodes, + .num_nodes = ARRAY_SIZE(msm8916_bimc_nodes), +}; + +static struct qcom_icc_node *msm8916_pnoc_nodes[] = { + &mas_audio, + &mas_blsp_1, + &mas_dehr, + &mas_pnoc_crypto_0, + &mas_pnoc_sdcc_1, + &mas_pnoc_sdcc_2, + &mas_spdm, + &mas_usb_hs, + &pnoc_int_0, + &pnoc_int_1, + &pnoc_m_0, + &pnoc_m_1, + &pnoc_s_0, + &pnoc_s_1, + &pnoc_s_2, + &pnoc_s_3, + &pnoc_s_4, + &pnoc_s_8, + &pnoc_s_9, + &pnoc_snoc_mas, + &slv_audio, + &slv_bimc_cfg, + &slv_blsp_1, + &slv_boot_rom, + &slv_camera_cfg, + &slv_clk_ctl, + &slv_crypto_0_cfg, + &slv_dehr_cfg, + &slv_display_cfg, + &slv_gfx_cfg, + &slv_imem_cfg, + &slv_mpm, + &slv_msg_ram, + &slv_mss, + &slv_pdm, + &slv_pmic_arb, + &slv_pnoc_cfg, + &slv_prng, + &slv_qdss_cfg, + &slv_rbcpr_cfg, + &slv_sdcc_1, + &slv_sdcc_2, + &slv_security, + &slv_snoc_cfg, + &slv_spdm, + &slv_tcsr, + &slv_tlmm, + &slv_usb_hs, + &slv_venus_cfg, + &snoc_pnoc_slv, +}; + +static struct qcom_icc_desc msm8916_pnoc = { + .nodes = msm8916_pnoc_nodes, + .num_nodes = ARRAY_SIZE(msm8916_pnoc_nodes), +}; + +static int qcom_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 qcom_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct qcom_icc_provider *qp; + struct qcom_icc_node *qn; + struct icc_provider *provider; + struct icc_node *n; + u64 sum_bw; + u64 max_peak_bw; + u64 rate; + u32 agg_avg = 0; + u32 agg_peak = 0; + int ret = 0; + + qn = src->data; + provider = src->provider; + qp = to_qcom_provider(provider); + + list_for_each_entry(n, &provider->nodes, node_list) + qcom_icc_aggregate(n, 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 */ + if (qn->ap_owned) { + /* TODO: set QoS */ + } else { + /* send message to the RPM processor */ + if (qn->mas_rpm_id != -1) { + ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, + RPM_BUS_MASTER_REQ, + qn->mas_rpm_id, + sum_bw); + if (ret) { + pr_err("qcom_icc_rpm_smd_send mas error %d\n", + ret); + return ret; + } + } + + if (qn->slv_rpm_id != -1) { + ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, + RPM_BUS_SLAVE_REQ, + qn->slv_rpm_id, + sum_bw); + if (ret) { + pr_err("qcom_icc_rpm_smd_send slv error %d\n", + ret); + return ret; + } + } + } + + rate = max(sum_bw, max_peak_bw); + + do_div(rate, qn->buswidth); + + if (qn->rate != rate) { + ret = clk_set_rate(qp->bus_clk, rate); + if (ret) { + pr_err("set clk rate %lld error %d\n", rate, ret); + return ret; + } + + ret = clk_set_rate(qp->bus_a_clk, rate); + if (ret) { + pr_err("set clk rate %lld error %d\n", rate, ret); + return ret; + } + + qn->rate = rate; + } + + return ret; +} + +static int qnoc_probe(struct platform_device *pdev) +{ + const struct qcom_icc_desc *desc; + struct qcom_icc_node **qnodes; + struct icc_node *node; + struct qcom_icc_provider *qp; + struct resource *res; + struct icc_provider *provider; + size_t num_nodes, i; + int ret; + + /* wait for RPM */ + if (!qcom_icc_rpm_smd_available()) + return -EPROBE_DEFER; + + desc = of_device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + qp->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(qp->base)) + return PTR_ERR(qp->base); + + qp->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); + if (IS_ERR(qp->bus_clk)) + return PTR_ERR(qp->bus_clk); + + ret = clk_prepare_enable(qp->bus_clk); + if (ret) { + dev_err(&pdev->dev, "error enabling bus_clk: %d\n", ret); + return ret; + } + + qp->bus_a_clk = devm_clk_get(&pdev->dev, "bus_a_clk"); + if (IS_ERR(qp->bus_a_clk)) + return PTR_ERR(qp->bus_a_clk); + + ret = clk_prepare_enable(qp->bus_a_clk); + if (ret) { + dev_err(&pdev->dev, "error enabling bus_a_clk: %d\n", ret); + clk_disable_unprepare(qp->bus_clk); + return ret; + } + + provider = &qp->provider; + provider->dev = &pdev->dev; + provider->set = &qcom_icc_set; + provider->aggregate = &qcom_icc_aggregate; + INIT_LIST_HEAD(&provider->nodes); + provider->data = qp; + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + return ret; + } + + for (i = 0; i < num_nodes; i++) { + int ret; + size_t j; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + dev_dbg(&pdev->dev, "registered node %s\n", node->name); + + /* populate links */ + for (j = 0; j < qnodes[i]->num_links; j++) + if (qnodes[i]->links[j]) + icc_link_create(node, qnodes[i]->links[j]); + } + + platform_set_drvdata(pdev, provider); + + return ret; +err: + list_for_each_entry(node, &provider->nodes, node_list) { + icc_node_del(node); + icc_node_destroy(node->id); + } + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + icc_provider_del(provider); + + return ret; +} + +static int qnoc_remove(struct platform_device *pdev) +{ + struct icc_provider *provider = platform_get_drvdata(pdev); + struct qcom_icc_provider *qp = to_qcom_provider(provider); + struct icc_node *n; + + list_for_each_entry(n, &provider->nodes, node_list) { + icc_node_del(n); + icc_node_destroy(n->id); + } + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + + return icc_provider_del(provider); +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,msm8916-pnoc", .data = &msm8916_pnoc }, + { .compatible = "qcom,msm8916-snoc", .data = &msm8916_snoc }, + { .compatible = "qcom,msm8916-bimc", .data = &msm8916_bimc }, + { }, +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-msm8916", + .of_match_table = qnoc_of_match, + }, +}; +module_platform_driver(qnoc_driver); +MODULE_AUTHOR("Georgi Djakov "); +MODULE_DESCRIPTION("Qualcomm msm8916 NoC driver"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Aug 10 14:52:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 10562777 X-Patchwork-Delegate: agross@codeaurora.org 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 2C72B1515 for ; Fri, 10 Aug 2018 14:53:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1CB5227FA9 for ; Fri, 10 Aug 2018 14:53:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0FB432832D; Fri, 10 Aug 2018 14:53:13 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 AF30827FA9 for ; Fri, 10 Aug 2018 14:53:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728861AbeHJRXN (ORCPT ); Fri, 10 Aug 2018 13:23:13 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:32954 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728834AbeHJRXM (ORCPT ); Fri, 10 Aug 2018 13:23:12 -0400 Received: by mail-wr1-f68.google.com with SMTP id g6-v6so8579263wrp.0 for ; Fri, 10 Aug 2018 07:52:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3nhe4ogehPXkAKYsCtMktZfIkdq4Qz0OXPXKO98cZNE=; b=MhgVMuXOWZiahjgtOSQvHexGyxlxRrvdwdTml8LUL8wu394seFOkWn6nifjyYtZATL wxenX0rsILaZuzo0Fg1sbP11SkSYlXvHX2AYILY5McYYUggbOTS0sHlAK6i0pdDQZZ+8 YkmeatiN57dp7/r8e/SgA62AZf26sUVOb4J9s= 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; bh=3nhe4ogehPXkAKYsCtMktZfIkdq4Qz0OXPXKO98cZNE=; b=BopVuTWOQTJPmBcQJJiN/MyYkoFepLCgA4j1A+3cs8EmdrbgNXEW8RCQ14x8A7gzED 8X3cMTA8vuz7FDTkTGVPxINBgBwcLb6m8l0jX+BXpMlNnx0W7F48YYwxb78xwl0/QZP4 r1gIZs6X3Im7nmPXar71ji0mm9/in8ypppqqPe59gqk4pGidpkJBmKI0v4Pez/WiMwPX B7/LkYqgVID+MfCznsNnm8lRKm6/BF/jDBS0Cc0dW+Pm6H71MTcX3MrZ0BhZOCdCgYf9 jfehZWJmkdhM1gPq/PZG43jEijCKv9OzFxa+dZRLmdFxbh79EiZTtzUfnJzop+yi+gnH FlpA== X-Gm-Message-State: AOUpUlFWe1mhTAZeNdSOF045nNQ8Grj4/OjooWt8qrnH8BO+0rdj/nnB RLelkg2V3pLqA7glurGFqI60ag== X-Google-Smtp-Source: AA+uWPwDJFVwwPNwQFiL8RulBjA6LXDZWzsgCyMbbskvMpcPdGfFjLAG78VDferPSI4bwhapqLnOCg== X-Received: by 2002:adf:b3d7:: with SMTP id x23-v6mr4453315wrd.253.1533912777660; Fri, 10 Aug 2018 07:52:57 -0700 (PDT) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 9-v6sm19842700wrb.48.2018.08.10.07.52.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Aug 2018 07:52:56 -0700 (PDT) From: Georgi Djakov To: linux-pm@vger.kernel.org, gregkh@linuxfoundation.org Cc: rjw@rjwysocki.net, robh+dt@kernel.org, mturquette@baylibre.com, khilman@baylibre.com, vincent.guittot@linaro.org, skannan@codeaurora.org, bjorn.andersson@linaro.org, amit.kucheria@linaro.org, seansw@qti.qualcomm.com, daidavid1@codeaurora.org, evgreen@chromium.org, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, abailon@baylibre.com, arnd@arndb.de, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v8 8/8] MAINTAINERS: add a maintainer for the interconnect API Date: Fri, 10 Aug 2018 17:52:33 +0300 Message-Id: <20180810145233.16466-9-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810145233.16466-1-georgi.djakov@linaro.org> References: <20180810145233.16466-1-georgi.djakov@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add myself as the maintainer of the interconnect API. Signed-off-by: Georgi Djakov --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 32fbc6f732d4..ed1b534c901b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7420,6 +7420,16 @@ L: linux-gpio@vger.kernel.org S: Maintained F: drivers/gpio/gpio-intel-mid.c +INTERCONNECT API +M: Georgi Djakov +S: Maintained +F: Documentation/interconnect/ +F: Documentation/devicetree/bindings/interconnect/ +F: drivers/interconnect/ +F: include/dt-bindings/interconnect/ +F: include/linux/interconnect-provider.h +F: include/linux/interconnect.h + INVENSENSE MPU-3050 GYROSCOPE DRIVER M: Linus Walleij L: linux-iio@vger.kernel.org