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: 143949 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp50525ljj; Fri, 10 Aug 2018 07:53:34 -0700 (PDT) X-Google-Smtp-Source: AA+uWPy65dfkb2y9v/szR3VI2Mf3AelIXTsx18WkxoNrcJDE5hbwihqnmb85LO256PdvCa9Gz1z/ X-Received: by 2002:a63:81c3:: with SMTP id t186-v6mr6901893pgd.413.1533912813961; Fri, 10 Aug 2018 07:53:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533912813; cv=none; d=google.com; s=arc-20160816; b=OOaEq8XLTiskTB5vw0ARPVnR1fKnSp4RdKyqGftnZ9RpUTxCD5NpufDA2nth8aGljF tJToLySzLuPnHzHIxvCueQZ2VbanZf0l+OKIYH2yuispHCq2t9C6dmIA6rjPWWBKbYF1 rgIP447Me0MrURuylno2Nm3cd9o7E6SNGvgwItYSK/mr/o95q/OV5BtpQh8xJOJlUb6J nxzOhV+wAUzId7jJeMuMtDf5ALIujGKMzTtQj8j4EY8lxx+TEUmRwElSmKsHmsDT4dlM apiWkSkFCXiJWjhxkfAZacHlYqRa6vNpeOUMlJqrjy2ZxDGaNi03y/heUYw0h4OshLZi HmqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=3oltLqGMpD1j1mfioWk+wn2DTufVbquuCtG8B9CVxjQ=; b=RM8j5O06lwpJm3cVJX5Umo1Hd5E+iuOtAQR7vz4mfMxJ5d1d+9LxDTud17Zp8+pEly 0RRYu9+zHJddWffYdhmXkDSZ1LN3eLsikQJmPsw0xBbFpi5lbNalQ9AVENvPZxySHetG sxI3NyLfgVcvPr8jMktReM/lJoTqH7sBBtEaZth6KZn8vwCzvhmBX+v4dS/gGRNN2btd ZKHNjYLGA/D1+KiGvz3XO6MBz9GV9qnNPdrAxu2rsrFd/SsUsyoCBo/UHKE41ZB7kATr K4UnxU2lC95Y7v0VJ5fOPjnV/sJdPSPF7eT0xWqfyXw8NE7iex7TlzMx2hIO897T4FG8 Cbdw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=j+QQQWAC; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c21-v6si8129556pls.407.2018.08.10.07.53.33; Fri, 10 Aug 2018 07:53:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=j+QQQWAC; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728267AbeHJRXB (ORCPT + 5 others); Fri, 10 Aug 2018 13:23:01 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:50190 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728185AbeHJRXA (ORCPT ); Fri, 10 Aug 2018 13:23:00 -0400 Received: by mail-wm0-f67.google.com with SMTP id s12-v6so2220739wmc.0 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=rkv6EIxQ4XiqGKJGl4DmH//5h1AXMzKmWMbIq/g4sv3o9MonAao7rYvuK0/sUPDtm3 RwEYKkM/CVlaiEBPyEvNybu9Ms7fPf7ku9VTuIdMmfA/pS5haHrIEXa8E4rPCDunjQPy fhqOrMO4XwBSpzaeOO82raN34t3gkC2YBkVtJXBeMxaF392thr19m/6M4/ywhxOyZC6E fjq/KYDtp+mbFE6x5fpxwDGerRYRwvO9dMUc5xlU7OfXEiQVD5z0l3h+F2iq1BlBkM6+ kJ2YGN5Buk/wng7nYLajmSGQWBOvicsvMoz8sH9d1dtIntPiShZILJiV/qV8LcY+jM+Q YeJg== X-Gm-Message-State: AOUpUlHtkxKqBgerX8jM1kCfcdbq9Uc+59COjx2Laq1aA92Xr74hzN1+ dC0SCmH7e57DsmDNXnvEctOoyw== 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: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org 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: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: 143944 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp49811ljj; Fri, 10 Aug 2018 07:52:54 -0700 (PDT) X-Google-Smtp-Source: AA+uWPy9edvTrVjbEupXEvh/hLyo+0d6EIhXvCD+v0KtToIugU0fuZAMGmNnptH/If2kyvyfGdjw X-Received: by 2002:a62:198e:: with SMTP id 136-v6mr7470939pfz.103.1533912774128; Fri, 10 Aug 2018 07:52:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533912774; cv=none; d=google.com; s=arc-20160816; b=q5O/D0QAjFB+uTOlA3dElUf3scD1nfO+XQTIh3Z5ZrVmwA+jCYNhmm4xhb87WvqwY/ thjoSIayGZRuBIr4+213NrmI3+fmwwZ9on1eXt9rJAchjlm8+hJLOyazsjJHb19wClBR z665LVJU92cO+bJDwIEMyj4MYEVMyYvsqMTDJarTXMDebAbQ82MC4Fje+o4y8N3K703Z zbaoKMs6OCGVYtqqVcWJzZZjs9VnZwEPZ973XkPqzKN5wki8XDWqsNU7v0IHitwnsX5r oJzQKr36LEZ/XhIzPCmjRRY8k+SdyozEVD+Rlj2XzQ1nztdGH593+STzoRlo9ni0Av2F 8tow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=K5qYFSU+P7Ie0HuaSbBHj2ureU4ns5TmNVNvVaDKFEI=; b=N2I1vZNKT5drA8OlM55Orb4e5byQxaZYf1/lGBdQBmunKQ/zcL0671A8Q+EiaZMgtc 57B/FRKRx7VjpCLYB5FuLZHfWQUigkSsrd2koJgsIsHmjgnTakrkq9cNXoQ7MD3ib0P9 +YcIb2wfhtZvNNe4DqvHTOhADxR1zghkqJwwvoXRZgqAwtqfyy5h0vI8WldDYxGJHobT GbB4ZQG4sjfPjPXKUxnI2V3+0iqZg2MAOp8TTDGZpiy84PFKQBPzLA7nXQFy1mtvvdiT RMblc8vuEZCv6jcT4VhQ9CUMpFEThHVIkKlglYcK7LTrQnsdUwO5W0O2AiQ9NfYW0dxa q/qA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Oc9dYoU0; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 127-v6si9200643pgi.38.2018.08.10.07.52.53; Fri, 10 Aug 2018 07:52:54 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Oc9dYoU0; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728438AbeHJRXF (ORCPT + 5 others); Fri, 10 Aug 2018 13:23:05 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:42593 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728278AbeHJRXF (ORCPT ); Fri, 10 Aug 2018 13:23:05 -0400 Received: by mail-wr1-f67.google.com with SMTP id e7-v6so8533192wrs.9 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=X4qTP/X5IZ1wfntVJE7LknzHv0NLVZc+2GUYgJJPCyw2PWsU/QDis0IORVCRjj105v WtrtofB0L0kq2Z96CIwqd5KKE8xWevB5tlyUo8ntH+uRAENvdfmDzjdubqx6ENm3F5dG NDsRFWLn4yqiNssYqaZGeCH1N39vPYUZ7pl10N97hUlvsoluTbaoGJuGl/XZtun27Poo aw4d/ZapsnKC3ke/rirM07rfbktG3bNWtTMJx2zjviiKt/cLVZ/8UOKZSMltHk1O46j9 gh47+NjDAOKaRRl3wyeX50O4MwZruHz/krVJXSu7cxEG0aw9AGXobh6llp+IyVVPzQV3 NuHQ== X-Gm-Message-State: AOUpUlFK8ffz0Yqq83mK9l4OWpDpBX/bhpvOb9ltoXpjomIVgPhwy37/ E8sn5Lq2mz4h8vfBO48ZIKXH3A== 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: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org 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: 143946 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp49878ljj; Fri, 10 Aug 2018 07:52:58 -0700 (PDT) X-Google-Smtp-Source: AA+uWPzLoYzux+dnqR/kGpv4ROnzswdIWa2Eh76Z/3nbkwlx1PTpTiSXgE6qtgj0bUC72NDkpN7q X-Received: by 2002:a63:460d:: with SMTP id t13-v6mr4220878pga.201.1533912778356; Fri, 10 Aug 2018 07:52:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533912778; cv=none; d=google.com; s=arc-20160816; b=sTdyLFxd8HyaqOKeyQxp64aC+7njhAMMWORfS1nCMgu8v617Nx9xksIoWych/eUuda V/MV2OtOXwzu7EMa/XXuF5qAhLCYpAnP9bKtiE3sXcQ7dY0eA9Podr41Y2WYJFjI5g4G IFdpkqM8tBMpF2dTGCfqPANPiWn+yGsFaMgXjiWpnZf25SlPrxblxzb7rnQfl+Vtu6vq e0vcEaf7lHQy2yoH91r9FlzsUZO8nzQSqbH+0YcIVkRqQzyrSKzbaPZM5QDCU7WOVtsP ohwzittvSJ6DRCNgPpVjzJBRFWLxL/yL1k3VV365NqbgVzLbNrS7RjWB+Ul7rmAQeHxt R3QQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=9oUIEusk495SIX9kXu/WUGAbH7L0f6JAltllXHNc7ks=; b=c0dn4Dw7HfzB4l0S5Z826eCx/5BgXPH6qpJrcPV3rqmMvyiwgfXC94Y4ljLQd/rLFf 0QlZjKugJ7uZBcEmVxXhxfZulv8BkzA/UFtiJkAOuIpsbjfhzX75Dd/BqDNYlgV/Clsk rJztpb9tbz1mEoD0Xm+gQvAYv2LaywdzJLMBaMc8NXhfHWTg0mxcE4m+uw2UQFQB6f6c STGizosR89HReYu4eCEBqSW+2n5ZHQeZwMYHHX58qH1dZlpx5EbYey2/rYzmVYRd2eaI 2ApMcvZPt2sgg5OmHVp/yd1iCR8n+9KGUDRLI7k7WYlfg4781bt3zZYFWfo/ODlM5Hap 4P1w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fDe9hhyt; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a3-v6si8642378pln.298.2018.08.10.07.52.58; Fri, 10 Aug 2018 07:52:58 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fDe9hhyt; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728635AbeHJRXJ (ORCPT + 5 others); Fri, 10 Aug 2018 13:23:09 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:44566 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728596AbeHJRXJ (ORCPT ); Fri, 10 Aug 2018 13:23:09 -0400 Received: by mail-wr1-f65.google.com with SMTP id r16-v6so8526703wrt.11 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=sY06J9s4nlk9sj2l8YHu4zwoBXESuw7b/g/DDqHAgM/Gj3CWhZfampIwTksfYFemO0 BTD9e4fgh5tIFEkMfOHjTu6r7a/jYfkv4cvSFY1aYpTlQpTmsLJmY/bIFiZdB4g2feF9 tN/rJroB5TK6WXageIeUZGbKsqiF9pUmrbgxHuQmMrxXfP7p//rkqv202chaK9Qn/wVa 0iKBO2wef5ug2Bn2wkXufjGYMnaKPw/Osa4RBqN+pAYFme6d6EiJCsmtGdykCiw+3vlW 3gz2WBtYo/B73y48GlmaKrVdPkIeGiYK2pcTsI0il5kdZD/BC7r63JJbychrmswEzNNw eXlQ== X-Gm-Message-State: AOUpUlFo6eYTDUDQ7fh1Tg1Ca94BeLFh+tlC9q5uIx9U/P3aNqQLwtd5 aH0h1R1SDd+LEzSeL0vRMYxayg== 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: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org 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