interconnect patches for 5.6

Here are the interconnect patches for the 5.6-rc1 merge window.
 
 - New core helper functions for some common functionalities in drivers.
 - Improvements in the information exposed via debugfs.
 - Basic tracepoints support.
 - New interconnect driver for msm8916 platforms.
 - Misc fixes.
 
 Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJeIXe2AAoJEIDQzArG2BZjmToQAMijCGSN8TkzoS1/9w95ML9Q
 vbth57JAjHRoigpIt2nVP9c/oIAqxprIB+ZsXX6pKUtnRVTJo/gviQEw1UCqMp58
 d1v2Yb/b8lyzAbXdiVHbFKjF7pdNRUZDraMZ7HSC3UGD1LIy5cx0YjqwYyWFJEz6
 +9Ko3uDYEGqh3HM4Ybl5X5F019tdYY8TrTpajnKnh9yQDh3SAzw5mEDc7PuldAFn
 jgd0KVx56LRKWpA7SKfCjfsS8h4Ft48yzaUATJdNlcihl09mvNYcJ8ZHrGod/n/B
 cBKSwdaKwK0/LuGHrEM6I4UmbbfTmiNJ9dImtMwo5XapBG+OFBNhcVukJrW5xINe
 D3N9hXdUWSnnQyT+sOm8U3cL70PiueKP/CofhEJ4UxBrlckYfPGCZLLTAi4+dfPS
 T2rTonMGNIBCoqZ7iLDGff8uVQxGfOJkdNfd/UpJ64OLshQIXU+WQfa9PbVzkTly
 5opGJlU4X261S3lxxYCKFAP0QGUyDvrzItSMBegcDvUFFwQN06ISMYdXp0VJh3xk
 vYXV3vokqKJZcU8/YBGlZU8DAlHMxtEETt2B+Ua2tuYMzyHFWd76aQt3q7Id0xRB
 Dp6FoZROyBMgH00FCAdAK25dhL0M2CiUpSjmgDXprZeMX1YJRz24zR4u+fJOmq5g
 XZpJM/HIdRlq9pHHEZ/h
 =5hpf
 -----END PGP SIGNATURE-----

Merge tag 'icc-5.6-rc1' of https://git.linaro.org/people/georgi.djakov/linux into char-misc-next

Georgi writes:

interconnect patches for 5.6

Here are the interconnect patches for the 5.6-rc1 merge window.

- New core helper functions for some common functionalities in drivers.
- Improvements in the information exposed via debugfs.
- Basic tracepoints support.
- New interconnect driver for msm8916 platforms.
- Misc fixes.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>

* tag 'icc-5.6-rc1' of https://git.linaro.org/people/georgi.djakov/linux:
  interconnect: qcom: Add MSM8916 interconnect provider driver
  dt-bindings: interconnect: Add Qualcomm MSM8916 DT bindings
  interconnect: Check for valid path in icc_set_bw()
  interconnect: Print the tag in the debugfs summary
  interconnect: Add interconnect_graph file to debugfs
  interconnect: qcom: Use the standard aggregate function
  interconnect: Add a common standard aggregate function
  interconnect: Add basic tracepoints
  interconnect: Add a name to struct icc_path
  interconnect: Move internal structs into a separate file
  interconnect: qcom: Use the new common helper for node removal
  interconnect: Add a common helper for removing all nodes
This commit is contained in:
Greg Kroah-Hartman 2020-01-22 10:04:39 +01:00
commit 10d3e38c79
14 changed files with 1057 additions and 100 deletions

View File

@ -0,0 +1,77 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/interconnect/qcom,msm8916.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm MSM8916 Network-On-Chip interconnect
maintainers:
- Georgi Djakov <georgi.djakov@linaro.org>
description: |
The Qualcomm MSM8916 interconnect providers support adjusting the
bandwidth requirements between the various NoC fabrics.
properties:
compatible:
enum:
- qcom,msm8916-bimc
- qcom,msm8916-pcnoc
- qcom,msm8916-snoc
reg:
maxItems: 1
'#interconnect-cells':
const: 1
clock-names:
items:
- const: bus
- const: bus_a
clocks:
items:
- description: Bus Clock
- description: Bus A Clock
required:
- compatible
- reg
- '#interconnect-cells'
- clock-names
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
bimc: interconnect@400000 {
compatible = "qcom,msm8916-bimc";
reg = <0x00400000 0x62000>;
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
<&rpmcc RPM_SMD_BIMC_A_CLK>;
};
pcnoc: interconnect@500000 {
compatible = "qcom,msm8916-pcnoc";
reg = <0x00500000 0x11000>;
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_PCNOC_CLK>,
<&rpmcc RPM_SMD_PCNOC_A_CLK>;
};
snoc: interconnect@580000 {
compatible = "qcom,msm8916-snoc";
reg = <0x00580000 0x14000>;
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
<&rpmcc RPM_SMD_SNOC_A_CLK>;
};

View File

@ -91,3 +91,25 @@ 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. These interfaces are not currently
documented.
Interconnect debugfs interfaces
-------------------------------
Like several other subsystems interconnect will create some files for debugging
and introspection. Files in debugfs are not considered ABI so application
software shouldn't rely on format details change between kernel versions.
``/sys/kernel/debug/interconnect/interconnect_summary``:
Show all interconnect nodes in the system with their aggregated bandwidth
request. Indented under each node show bandwidth requests from each device.
``/sys/kernel/debug/interconnect/interconnect_graph``:
Show the interconnect graph in the graphviz dot format. It shows all
interconnect nodes and links in the system and groups together nodes from the
same provider as subgraphs. The format is human-readable and can also be piped
through dot to generate diagrams in many graphical formats::
$ cat /sys/kernel/debug/interconnect/interconnect_graph | \
dot -Tsvg > interconnect_graph.svg

View File

@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
CFLAGS_core.o := -I$(src)
icc-core-objs := core.o
obj-$(CONFIG_INTERCONNECT) += icc-core.o

View File

@ -19,45 +19,22 @@
#include <linux/of.h>
#include <linux/overflow.h>
#include "internal.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
static DEFINE_IDR(icc_idr);
static LIST_HEAD(icc_providers);
static DEFINE_MUTEX(icc_lock);
static struct dentry *icc_debugfs_dir;
/**
* 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
* @tag: path tag (optional)
* @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 tag;
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 void icc_summary_show_one(struct seq_file *s, struct icc_node *n)
{
if (!n)
return;
seq_printf(s, "%-30s %12u %12u\n",
seq_printf(s, "%-42s %12u %12u\n",
n->name, n->avg_bw, n->peak_bw);
}
@ -65,8 +42,8 @@ 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");
seq_puts(s, " node tag avg peak\n");
seq_puts(s, "--------------------------------------------------------------------\n");
mutex_lock(&icc_lock);
@ -81,8 +58,8 @@ static int icc_summary_show(struct seq_file *s, void *data)
if (!r->dev)
continue;
seq_printf(s, " %-26s %12u %12u\n",
dev_name(r->dev), r->avg_bw,
seq_printf(s, " %-27s %12u %12u %12u\n",
dev_name(r->dev), r->tag, r->avg_bw,
r->peak_bw);
}
}
@ -94,6 +71,70 @@ static int icc_summary_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(icc_summary);
static void icc_graph_show_link(struct seq_file *s, int level,
struct icc_node *n, struct icc_node *m)
{
seq_printf(s, "%s\"%d:%s\" -> \"%d:%s\"\n",
level == 2 ? "\t\t" : "\t",
n->id, n->name, m->id, m->name);
}
static void icc_graph_show_node(struct seq_file *s, struct icc_node *n)
{
seq_printf(s, "\t\t\"%d:%s\" [label=\"%d:%s",
n->id, n->name, n->id, n->name);
seq_printf(s, "\n\t\t\t|avg_bw=%ukBps", n->avg_bw);
seq_printf(s, "\n\t\t\t|peak_bw=%ukBps", n->peak_bw);
seq_puts(s, "\"]\n");
}
static int icc_graph_show(struct seq_file *s, void *data)
{
struct icc_provider *provider;
struct icc_node *n;
int cluster_index = 0;
int i;
seq_puts(s, "digraph {\n\trankdir = LR\n\tnode [shape = record]\n");
mutex_lock(&icc_lock);
/* draw providers as cluster subgraphs */
cluster_index = 0;
list_for_each_entry(provider, &icc_providers, provider_list) {
seq_printf(s, "\tsubgraph cluster_%d {\n", ++cluster_index);
if (provider->dev)
seq_printf(s, "\t\tlabel = \"%s\"\n",
dev_name(provider->dev));
/* draw nodes */
list_for_each_entry(n, &provider->nodes, node_list)
icc_graph_show_node(s, n);
/* draw internal links */
list_for_each_entry(n, &provider->nodes, node_list)
for (i = 0; i < n->num_links; ++i)
if (n->provider == n->links[i]->provider)
icc_graph_show_link(s, 2, n,
n->links[i]);
seq_puts(s, "\t}\n");
}
/* draw external links */
list_for_each_entry(provider, &icc_providers, provider_list)
list_for_each_entry(n, &provider->nodes, node_list)
for (i = 0; i < n->num_links; ++i)
if (n->provider != n->links[i]->provider)
icc_graph_show_link(s, 1, n,
n->links[i]);
mutex_unlock(&icc_lock);
seq_puts(s, "}");
return 0;
}
DEFINE_SHOW_ATTRIBUTE(icc_graph);
static struct icc_node *node_find(const int id)
{
return idr_find(&icc_idr, id);
@ -244,6 +285,16 @@ static int apply_constraints(struct icc_path *path)
return ret;
}
int icc_std_aggregate(struct icc_node *node, u32 tag, 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;
}
EXPORT_SYMBOL_GPL(icc_std_aggregate);
/* of_icc_xlate_onecell() - Translate function using a single index.
* @spec: OF phandle args to map into an interconnect node.
* @data: private data (pointer to struct icc_onecell_data)
@ -382,9 +433,17 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
mutex_lock(&icc_lock);
path = path_find(dev, src_node, dst_node);
if (IS_ERR(path))
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
mutex_unlock(&icc_lock);
if (IS_ERR(path)) {
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
return path;
}
if (name)
path->name = kstrdup_const(name, GFP_KERNEL);
else
path->name = kasprintf(GFP_KERNEL, "%s-%s",
src_node->name, dst_node->name);
return path;
}
@ -436,9 +495,12 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
size_t i;
int ret;
if (!path || !path->num_nodes)
if (!path)
return 0;
if (WARN_ON(IS_ERR(path) || !path->num_nodes))
return -EINVAL;
mutex_lock(&icc_lock);
old_avg = path->reqs[0].avg_bw;
@ -453,6 +515,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
/* aggregate requests for this node */
aggregate_requests(node);
trace_icc_set_bw(path, node, i, avg_bw, peak_bw);
}
ret = apply_constraints(path);
@ -471,6 +535,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
mutex_unlock(&icc_lock);
trace_icc_set_bw_end(path, ret);
return ret;
}
EXPORT_SYMBOL_GPL(icc_set_bw);
@ -507,9 +573,12 @@ struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id)
goto out;
path = path_find(dev, src, dst);
if (IS_ERR(path))
if (IS_ERR(path)) {
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
goto out;
}
path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name);
out:
mutex_unlock(&icc_lock);
return path;
@ -545,6 +614,7 @@ void icc_put(struct icc_path *path)
}
mutex_unlock(&icc_lock);
kfree_const(path->name);
kfree(path);
}
EXPORT_SYMBOL_GPL(icc_put);
@ -742,6 +812,28 @@ void icc_node_del(struct icc_node *node)
}
EXPORT_SYMBOL_GPL(icc_node_del);
/**
* icc_nodes_remove() - remove all previously added nodes from provider
* @provider: the interconnect provider we are removing nodes from
*
* Return: 0 on success, or an error code otherwise
*/
int icc_nodes_remove(struct icc_provider *provider)
{
struct icc_node *n, *tmp;
if (WARN_ON(IS_ERR_OR_NULL(provider)))
return -EINVAL;
list_for_each_entry_safe_reverse(n, tmp, &provider->nodes, node_list) {
icc_node_del(n);
icc_node_destroy(n->id);
}
return 0;
}
EXPORT_SYMBOL_GPL(icc_nodes_remove);
/**
* icc_provider_add() - add a new interconnect provider
* @provider: the interconnect provider that will be added into topology
@ -802,6 +894,8 @@ static int __init icc_init(void)
icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
debugfs_create_file("interconnect_summary", 0444,
icc_debugfs_dir, NULL, &icc_summary_fops);
debugfs_create_file("interconnect_graph", 0444,
icc_debugfs_dir, NULL, &icc_graph_fops);
return 0;
}

View File

@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Interconnect framework internal structs
*
* Copyright (c) 2019, Linaro Ltd.
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#ifndef __DRIVERS_INTERCONNECT_INTERNAL_H
#define __DRIVERS_INTERCONNECT_INTERNAL_H
/**
* 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
* @tag: path tag (optional)
* @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 tag;
u32 avg_bw;
u32 peak_bw;
};
/**
* struct icc_path - interconnect path structure
* @name: a string name of the path (useful for ftrace)
* @num_nodes: number of hops (nodes)
* @reqs: array of the requests applicable to this path of nodes
*/
struct icc_path {
const char *name;
size_t num_nodes;
struct icc_req reqs[];
};
#endif

View File

@ -5,6 +5,15 @@ config INTERCONNECT_QCOM
help
Support for Qualcomm's Network-on-Chip interconnect hardware.
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.
config INTERCONNECT_QCOM_MSM8974
tristate "Qualcomm MSM8974 interconnect driver"
depends on INTERCONNECT_QCOM

View File

@ -1,10 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
qnoc-msm8916-objs := msm8916.o
qnoc-msm8974-objs := msm8974.o
qnoc-qcs404-objs := qcs404.o
qnoc-sdm845-objs := sdm845.o
icc-smd-rpm-objs := smd-rpm.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o

View File

@ -0,0 +1,554 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018-2020 Linaro Ltd
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <dt-bindings/interconnect/qcom,msm8916.h>
#include "smd-rpm.h"
#define RPM_BUS_MASTER_REQ 0x73616d62
#define RPM_BUS_SLAVE_REQ 0x766c7362
enum {
MSM8916_BIMC_SNOC_MAS = 1,
MSM8916_BIMC_SNOC_SLV,
MSM8916_MASTER_AMPSS_M0,
MSM8916_MASTER_LPASS,
MSM8916_MASTER_BLSP_1,
MSM8916_MASTER_DEHR,
MSM8916_MASTER_GRAPHICS_3D,
MSM8916_MASTER_JPEG,
MSM8916_MASTER_MDP_PORT0,
MSM8916_MASTER_CRYPTO_CORE0,
MSM8916_MASTER_SDCC_1,
MSM8916_MASTER_SDCC_2,
MSM8916_MASTER_QDSS_BAM,
MSM8916_MASTER_QDSS_ETR,
MSM8916_MASTER_SNOC_CFG,
MSM8916_MASTER_SPDM,
MSM8916_MASTER_TCU0,
MSM8916_MASTER_TCU1,
MSM8916_MASTER_USB_HS,
MSM8916_MASTER_VFE,
MSM8916_MASTER_VIDEO_P0,
MSM8916_SNOC_MM_INT_0,
MSM8916_SNOC_MM_INT_1,
MSM8916_SNOC_MM_INT_2,
MSM8916_SNOC_MM_INT_BIMC,
MSM8916_PNOC_INT_0,
MSM8916_PNOC_INT_1,
MSM8916_PNOC_MAS_0,
MSM8916_PNOC_MAS_1,
MSM8916_PNOC_SLV_0,
MSM8916_PNOC_SLV_1,
MSM8916_PNOC_SLV_2,
MSM8916_PNOC_SLV_3,
MSM8916_PNOC_SLV_4,
MSM8916_PNOC_SLV_8,
MSM8916_PNOC_SLV_9,
MSM8916_PNOC_SNOC_MAS,
MSM8916_PNOC_SNOC_SLV,
MSM8916_SNOC_QDSS_INT,
MSM8916_SLAVE_AMPSS_L2,
MSM8916_SLAVE_APSS,
MSM8916_SLAVE_LPASS,
MSM8916_SLAVE_BIMC_CFG,
MSM8916_SLAVE_BLSP_1,
MSM8916_SLAVE_BOOT_ROM,
MSM8916_SLAVE_CAMERA_CFG,
MSM8916_SLAVE_CATS_128,
MSM8916_SLAVE_OCMEM_64,
MSM8916_SLAVE_CLK_CTL,
MSM8916_SLAVE_CRYPTO_0_CFG,
MSM8916_SLAVE_DEHR_CFG,
MSM8916_SLAVE_DISPLAY_CFG,
MSM8916_SLAVE_EBI_CH0,
MSM8916_SLAVE_GRAPHICS_3D_CFG,
MSM8916_SLAVE_IMEM_CFG,
MSM8916_SLAVE_IMEM,
MSM8916_SLAVE_MPM,
MSM8916_SLAVE_MSG_RAM,
MSM8916_SLAVE_MSS,
MSM8916_SLAVE_PDM,
MSM8916_SLAVE_PMIC_ARB,
MSM8916_SLAVE_PNOC_CFG,
MSM8916_SLAVE_PRNG,
MSM8916_SLAVE_QDSS_CFG,
MSM8916_SLAVE_QDSS_STM,
MSM8916_SLAVE_RBCPR_CFG,
MSM8916_SLAVE_SDCC_1,
MSM8916_SLAVE_SDCC_2,
MSM8916_SLAVE_SECURITY,
MSM8916_SLAVE_SNOC_CFG,
MSM8916_SLAVE_SPDM,
MSM8916_SLAVE_SRVC_SNOC,
MSM8916_SLAVE_TCSR,
MSM8916_SLAVE_TLMM,
MSM8916_SLAVE_USB_HS,
MSM8916_SLAVE_VENUS_CFG,
MSM8916_SNOC_BIMC_0_MAS,
MSM8916_SNOC_BIMC_0_SLV,
MSM8916_SNOC_BIMC_1_MAS,
MSM8916_SNOC_BIMC_1_SLV,
MSM8916_SNOC_INT_0,
MSM8916_SNOC_INT_1,
MSM8916_SNOC_INT_BIMC,
MSM8916_SNOC_PNOC_MAS,
MSM8916_SNOC_PNOC_SLV,
};
#define to_msm8916_provider(_provider) \
container_of(_provider, struct msm8916_icc_provider, provider)
static const struct clk_bulk_data msm8916_bus_clocks[] = {
{ .id = "bus" },
{ .id = "bus_a" },
};
/**
* struct msm8916_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
* @bus_clks: the clk_bulk_data table of bus clocks
* @num_clks: the total number of clk_bulk_data entries
*/
struct msm8916_icc_provider {
struct icc_provider provider;
struct clk_bulk_data *bus_clks;
int num_clks;
};
#define MSM8916_MAX_LINKS 8
/**
* struct msm8916_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
* @buswidth: width of the interconnect between a node and the bus (bytes)
* @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 msm8916_icc_node {
unsigned char *name;
u16 id;
u16 links[MSM8916_MAX_LINKS];
u16 num_links;
u16 buswidth;
int mas_rpm_id;
int slv_rpm_id;
u64 rate;
};
struct msm8916_icc_desc {
struct msm8916_icc_node **nodes;
size_t num_nodes;
};
#define DEFINE_QNODE(_name, _id, _buswidth, _mas_rpm_id, _slv_rpm_id, \
...) \
static struct msm8916_icc_node _name = { \
.name = #_name, \
.id = _id, \
.buswidth = _buswidth, \
.mas_rpm_id = _mas_rpm_id, \
.slv_rpm_id = _slv_rpm_id, \
.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \
.links = { __VA_ARGS__ }, \
}
DEFINE_QNODE(bimc_snoc_mas, MSM8916_BIMC_SNOC_MAS, 8, -1, -1, MSM8916_BIMC_SNOC_SLV);
DEFINE_QNODE(bimc_snoc_slv, MSM8916_BIMC_SNOC_SLV, 8, -1, -1, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_1);
DEFINE_QNODE(mas_apss, MSM8916_MASTER_AMPSS_M0, 8, -1, -1, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2);
DEFINE_QNODE(mas_audio, MSM8916_MASTER_LPASS, 4, -1, -1, MSM8916_PNOC_MAS_0);
DEFINE_QNODE(mas_blsp_1, MSM8916_MASTER_BLSP_1, 4, -1, -1, MSM8916_PNOC_MAS_1);
DEFINE_QNODE(mas_dehr, MSM8916_MASTER_DEHR, 4, -1, -1, MSM8916_PNOC_MAS_0);
DEFINE_QNODE(mas_gfx, MSM8916_MASTER_GRAPHICS_3D, 8, -1, -1, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2);
DEFINE_QNODE(mas_jpeg, MSM8916_MASTER_JPEG, 16, -1, -1, MSM8916_SNOC_MM_INT_0, MSM8916_SNOC_MM_INT_2);
DEFINE_QNODE(mas_mdp, MSM8916_MASTER_MDP_PORT0, 16, -1, -1, MSM8916_SNOC_MM_INT_0, MSM8916_SNOC_MM_INT_2);
DEFINE_QNODE(mas_pcnoc_crypto_0, MSM8916_MASTER_CRYPTO_CORE0, 8, -1, -1, MSM8916_PNOC_INT_1);
DEFINE_QNODE(mas_pcnoc_sdcc_1, MSM8916_MASTER_SDCC_1, 8, -1, -1, MSM8916_PNOC_INT_1);
DEFINE_QNODE(mas_pcnoc_sdcc_2, MSM8916_MASTER_SDCC_2, 8, -1, -1, MSM8916_PNOC_INT_1);
DEFINE_QNODE(mas_qdss_bam, MSM8916_MASTER_QDSS_BAM, 8, -1, -1, MSM8916_SNOC_QDSS_INT);
DEFINE_QNODE(mas_qdss_etr, MSM8916_MASTER_QDSS_ETR, 8, -1, -1, MSM8916_SNOC_QDSS_INT);
DEFINE_QNODE(mas_snoc_cfg, MSM8916_MASTER_SNOC_CFG, 4, 20, -1, MSM8916_SNOC_QDSS_INT);
DEFINE_QNODE(mas_spdm, MSM8916_MASTER_SPDM, 4, -1, -1, MSM8916_PNOC_MAS_0);
DEFINE_QNODE(mas_tcu0, MSM8916_MASTER_TCU0, 8, -1, -1, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2);
DEFINE_QNODE(mas_tcu1, MSM8916_MASTER_TCU1, 8, -1, -1, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2);
DEFINE_QNODE(mas_usb_hs, MSM8916_MASTER_USB_HS, 4, -1, -1, MSM8916_PNOC_MAS_1);
DEFINE_QNODE(mas_vfe, MSM8916_MASTER_VFE, 16, -1, -1, MSM8916_SNOC_MM_INT_1, MSM8916_SNOC_MM_INT_2);
DEFINE_QNODE(mas_video, MSM8916_MASTER_VIDEO_P0, 16, -1, -1, MSM8916_SNOC_MM_INT_0, MSM8916_SNOC_MM_INT_2);
DEFINE_QNODE(mm_int_0, MSM8916_SNOC_MM_INT_0, 16, -1, -1, MSM8916_SNOC_MM_INT_BIMC);
DEFINE_QNODE(mm_int_1, MSM8916_SNOC_MM_INT_1, 16, -1, -1, MSM8916_SNOC_MM_INT_BIMC);
DEFINE_QNODE(mm_int_2, MSM8916_SNOC_MM_INT_2, 16, -1, -1, MSM8916_SNOC_INT_0);
DEFINE_QNODE(mm_int_bimc, MSM8916_SNOC_MM_INT_BIMC, 16, -1, -1, MSM8916_SNOC_BIMC_1_MAS);
DEFINE_QNODE(pcnoc_int_0, MSM8916_PNOC_INT_0, 8, -1, -1, MSM8916_PNOC_SNOC_MAS, MSM8916_PNOC_SLV_0, MSM8916_PNOC_SLV_1, MSM8916_PNOC_SLV_2, MSM8916_PNOC_SLV_3, MSM8916_PNOC_SLV_4, MSM8916_PNOC_SLV_8, MSM8916_PNOC_SLV_9);
DEFINE_QNODE(pcnoc_int_1, MSM8916_PNOC_INT_1, 8, -1, -1, MSM8916_PNOC_SNOC_MAS);
DEFINE_QNODE(pcnoc_m_0, MSM8916_PNOC_MAS_0, 8, -1, -1, MSM8916_PNOC_INT_0);
DEFINE_QNODE(pcnoc_m_1, MSM8916_PNOC_MAS_1, 8, -1, -1, MSM8916_PNOC_SNOC_MAS);
DEFINE_QNODE(pcnoc_s_0, MSM8916_PNOC_SLV_0, 8, -1, -1, MSM8916_SLAVE_CLK_CTL, MSM8916_SLAVE_TLMM, MSM8916_SLAVE_TCSR, MSM8916_SLAVE_SECURITY, MSM8916_SLAVE_MSS);
DEFINE_QNODE(pcnoc_s_1, MSM8916_PNOC_SLV_1, 8, -1, -1, MSM8916_SLAVE_IMEM_CFG, MSM8916_SLAVE_CRYPTO_0_CFG, MSM8916_SLAVE_MSG_RAM, MSM8916_SLAVE_PDM, MSM8916_SLAVE_PRNG);
DEFINE_QNODE(pcnoc_s_2, MSM8916_PNOC_SLV_2, 8, -1, -1, MSM8916_SLAVE_SPDM, MSM8916_SLAVE_BOOT_ROM, MSM8916_SLAVE_BIMC_CFG, MSM8916_SLAVE_PNOC_CFG, MSM8916_SLAVE_PMIC_ARB);
DEFINE_QNODE(pcnoc_s_3, MSM8916_PNOC_SLV_3, 8, -1, -1, MSM8916_SLAVE_MPM, MSM8916_SLAVE_SNOC_CFG, MSM8916_SLAVE_RBCPR_CFG, MSM8916_SLAVE_QDSS_CFG, MSM8916_SLAVE_DEHR_CFG);
DEFINE_QNODE(pcnoc_s_4, MSM8916_PNOC_SLV_4, 8, -1, -1, MSM8916_SLAVE_VENUS_CFG, MSM8916_SLAVE_CAMERA_CFG, MSM8916_SLAVE_DISPLAY_CFG);
DEFINE_QNODE(pcnoc_s_8, MSM8916_PNOC_SLV_8, 8, -1, -1, MSM8916_SLAVE_USB_HS, MSM8916_SLAVE_SDCC_1, MSM8916_SLAVE_BLSP_1);
DEFINE_QNODE(pcnoc_s_9, MSM8916_PNOC_SLV_9, 8, -1, -1, MSM8916_SLAVE_SDCC_2, MSM8916_SLAVE_LPASS, MSM8916_SLAVE_GRAPHICS_3D_CFG);
DEFINE_QNODE(pcnoc_snoc_mas, MSM8916_PNOC_SNOC_MAS, 8, 29, -1, MSM8916_PNOC_SNOC_SLV);
DEFINE_QNODE(pcnoc_snoc_slv, MSM8916_PNOC_SNOC_SLV, 8, -1, 45, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC, MSM8916_SNOC_INT_1);
DEFINE_QNODE(qdss_int, MSM8916_SNOC_QDSS_INT, 8, -1, -1, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC);
DEFINE_QNODE(slv_apps_l2, MSM8916_SLAVE_AMPSS_L2, 8, -1, -1, 0);
DEFINE_QNODE(slv_apss, MSM8916_SLAVE_APSS, 4, -1, 20, 0);
DEFINE_QNODE(slv_audio, MSM8916_SLAVE_LPASS, 4, -1, -1, 0);
DEFINE_QNODE(slv_bimc_cfg, MSM8916_SLAVE_BIMC_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_blsp_1, MSM8916_SLAVE_BLSP_1, 4, -1, -1, 0);
DEFINE_QNODE(slv_boot_rom, MSM8916_SLAVE_BOOT_ROM, 4, -1, -1, 0);
DEFINE_QNODE(slv_camera_cfg, MSM8916_SLAVE_CAMERA_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_cats_0, MSM8916_SLAVE_CATS_128, 16, -1, 106, 0);
DEFINE_QNODE(slv_cats_1, MSM8916_SLAVE_OCMEM_64, 8, -1, 107, 0);
DEFINE_QNODE(slv_clk_ctl, MSM8916_SLAVE_CLK_CTL, 4, -1, -1, 0);
DEFINE_QNODE(slv_crypto_0_cfg, MSM8916_SLAVE_CRYPTO_0_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_dehr_cfg, MSM8916_SLAVE_DEHR_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_display_cfg, MSM8916_SLAVE_DISPLAY_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_ebi_ch0, MSM8916_SLAVE_EBI_CH0, 8, -1, 0, 0);
DEFINE_QNODE(slv_gfx_cfg, MSM8916_SLAVE_GRAPHICS_3D_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_imem_cfg, MSM8916_SLAVE_IMEM_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_imem, MSM8916_SLAVE_IMEM, 8, -1, 26, 0);
DEFINE_QNODE(slv_mpm, MSM8916_SLAVE_MPM, 4, -1, -1, 0);
DEFINE_QNODE(slv_msg_ram, MSM8916_SLAVE_MSG_RAM, 4, -1, -1, 0);
DEFINE_QNODE(slv_mss, MSM8916_SLAVE_MSS, 4, -1, -1, 0);
DEFINE_QNODE(slv_pdm, MSM8916_SLAVE_PDM, 4, -1, -1, 0);
DEFINE_QNODE(slv_pmic_arb, MSM8916_SLAVE_PMIC_ARB, 4, -1, -1, 0);
DEFINE_QNODE(slv_pcnoc_cfg, MSM8916_SLAVE_PNOC_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_prng, MSM8916_SLAVE_PRNG, 4, -1, -1, 0);
DEFINE_QNODE(slv_qdss_cfg, MSM8916_SLAVE_QDSS_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_qdss_stm, MSM8916_SLAVE_QDSS_STM, 4, -1, 30, 0);
DEFINE_QNODE(slv_rbcpr_cfg, MSM8916_SLAVE_RBCPR_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_sdcc_1, MSM8916_SLAVE_SDCC_1, 4, -1, -1, 0);
DEFINE_QNODE(slv_sdcc_2, MSM8916_SLAVE_SDCC_2, 4, -1, -1, 0);
DEFINE_QNODE(slv_security, MSM8916_SLAVE_SECURITY, 4, -1, -1, 0);
DEFINE_QNODE(slv_snoc_cfg, MSM8916_SLAVE_SNOC_CFG, 4, -1, -1, 0);
DEFINE_QNODE(slv_spdm, MSM8916_SLAVE_SPDM, 4, -1, -1, 0);
DEFINE_QNODE(slv_srvc_snoc, MSM8916_SLAVE_SRVC_SNOC, 8, -1, 29, 0);
DEFINE_QNODE(slv_tcsr, MSM8916_SLAVE_TCSR, 4, -1, -1, 0);
DEFINE_QNODE(slv_tlmm, MSM8916_SLAVE_TLMM, 4, -1, -1, 0);
DEFINE_QNODE(slv_usb_hs, MSM8916_SLAVE_USB_HS, 4, -1, -1, 0);
DEFINE_QNODE(slv_venus_cfg, MSM8916_SLAVE_VENUS_CFG, 4, -1, -1, 0);
DEFINE_QNODE(snoc_bimc_0_mas, MSM8916_SNOC_BIMC_0_MAS, 8, 3, -1, MSM8916_SNOC_BIMC_0_SLV);
DEFINE_QNODE(snoc_bimc_0_slv, MSM8916_SNOC_BIMC_0_SLV, 8, -1, 24, MSM8916_SLAVE_EBI_CH0);
DEFINE_QNODE(snoc_bimc_1_mas, MSM8916_SNOC_BIMC_1_MAS, 16, -1, -1, MSM8916_SNOC_BIMC_1_SLV);
DEFINE_QNODE(snoc_bimc_1_slv, MSM8916_SNOC_BIMC_1_SLV, 8, -1, -1, MSM8916_SLAVE_EBI_CH0);
DEFINE_QNODE(snoc_int_0, MSM8916_SNOC_INT_0, 8, 99, 130, MSM8916_SLAVE_QDSS_STM, MSM8916_SLAVE_IMEM, MSM8916_SNOC_PNOC_MAS);
DEFINE_QNODE(snoc_int_1, MSM8916_SNOC_INT_1, 8, 100, 131, MSM8916_SLAVE_APSS, MSM8916_SLAVE_CATS_128, MSM8916_SLAVE_OCMEM_64);
DEFINE_QNODE(snoc_int_bimc, MSM8916_SNOC_INT_BIMC, 8, 101, 132, MSM8916_SNOC_BIMC_0_MAS);
DEFINE_QNODE(snoc_pcnoc_mas, MSM8916_SNOC_PNOC_MAS, 8, -1, -1, MSM8916_SNOC_PNOC_SLV);
DEFINE_QNODE(snoc_pcnoc_slv, MSM8916_SNOC_PNOC_SLV, 8, -1, -1, MSM8916_PNOC_INT_0);
static struct msm8916_icc_node *msm8916_snoc_nodes[] = {
[BIMC_SNOC_SLV] = &bimc_snoc_slv,
[MASTER_JPEG] = &mas_jpeg,
[MASTER_MDP_PORT0] = &mas_mdp,
[MASTER_QDSS_BAM] = &mas_qdss_bam,
[MASTER_QDSS_ETR] = &mas_qdss_etr,
[MASTER_SNOC_CFG] = &mas_snoc_cfg,
[MASTER_VFE] = &mas_vfe,
[MASTER_VIDEO_P0] = &mas_video,
[SNOC_MM_INT_0] = &mm_int_0,
[SNOC_MM_INT_1] = &mm_int_1,
[SNOC_MM_INT_2] = &mm_int_2,
[SNOC_MM_INT_BIMC] = &mm_int_bimc,
[PCNOC_SNOC_SLV] = &pcnoc_snoc_slv,
[SLAVE_APSS] = &slv_apss,
[SLAVE_CATS_128] = &slv_cats_0,
[SLAVE_OCMEM_64] = &slv_cats_1,
[SLAVE_IMEM] = &slv_imem,
[SLAVE_QDSS_STM] = &slv_qdss_stm,
[SLAVE_SRVC_SNOC] = &slv_srvc_snoc,
[SNOC_BIMC_0_MAS] = &snoc_bimc_0_mas,
[SNOC_BIMC_1_MAS] = &snoc_bimc_1_mas,
[SNOC_INT_0] = &snoc_int_0,
[SNOC_INT_1] = &snoc_int_1,
[SNOC_INT_BIMC] = &snoc_int_bimc,
[SNOC_PCNOC_MAS] = &snoc_pcnoc_mas,
[SNOC_QDSS_INT] = &qdss_int,
};
static struct msm8916_icc_desc msm8916_snoc = {
.nodes = msm8916_snoc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_snoc_nodes),
};
static struct msm8916_icc_node *msm8916_bimc_nodes[] = {
[BIMC_SNOC_MAS] = &bimc_snoc_mas,
[MASTER_AMPSS_M0] = &mas_apss,
[MASTER_GRAPHICS_3D] = &mas_gfx,
[MASTER_TCU0] = &mas_tcu0,
[MASTER_TCU1] = &mas_tcu1,
[SLAVE_AMPSS_L2] = &slv_apps_l2,
[SLAVE_EBI_CH0] = &slv_ebi_ch0,
[SNOC_BIMC_0_SLV] = &snoc_bimc_0_slv,
[SNOC_BIMC_1_SLV] = &snoc_bimc_1_slv,
};
static struct msm8916_icc_desc msm8916_bimc = {
.nodes = msm8916_bimc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_bimc_nodes),
};
static struct msm8916_icc_node *msm8916_pcnoc_nodes[] = {
[MASTER_BLSP_1] = &mas_blsp_1,
[MASTER_DEHR] = &mas_dehr,
[MASTER_LPASS] = &mas_audio,
[MASTER_CRYPTO_CORE0] = &mas_pcnoc_crypto_0,
[MASTER_SDCC_1] = &mas_pcnoc_sdcc_1,
[MASTER_SDCC_2] = &mas_pcnoc_sdcc_2,
[MASTER_SPDM] = &mas_spdm,
[MASTER_USB_HS] = &mas_usb_hs,
[PCNOC_INT_0] = &pcnoc_int_0,
[PCNOC_INT_1] = &pcnoc_int_1,
[PCNOC_MAS_0] = &pcnoc_m_0,
[PCNOC_MAS_1] = &pcnoc_m_1,
[PCNOC_SLV_0] = &pcnoc_s_0,
[PCNOC_SLV_1] = &pcnoc_s_1,
[PCNOC_SLV_2] = &pcnoc_s_2,
[PCNOC_SLV_3] = &pcnoc_s_3,
[PCNOC_SLV_4] = &pcnoc_s_4,
[PCNOC_SLV_8] = &pcnoc_s_8,
[PCNOC_SLV_9] = &pcnoc_s_9,
[PCNOC_SNOC_MAS] = &pcnoc_snoc_mas,
[SLAVE_BIMC_CFG] = &slv_bimc_cfg,
[SLAVE_BLSP_1] = &slv_blsp_1,
[SLAVE_BOOT_ROM] = &slv_boot_rom,
[SLAVE_CAMERA_CFG] = &slv_camera_cfg,
[SLAVE_CLK_CTL] = &slv_clk_ctl,
[SLAVE_CRYPTO_0_CFG] = &slv_crypto_0_cfg,
[SLAVE_DEHR_CFG] = &slv_dehr_cfg,
[SLAVE_DISPLAY_CFG] = &slv_display_cfg,
[SLAVE_GRAPHICS_3D_CFG] = &slv_gfx_cfg,
[SLAVE_IMEM_CFG] = &slv_imem_cfg,
[SLAVE_LPASS] = &slv_audio,
[SLAVE_MPM] = &slv_mpm,
[SLAVE_MSG_RAM] = &slv_msg_ram,
[SLAVE_MSS] = &slv_mss,
[SLAVE_PDM] = &slv_pdm,
[SLAVE_PMIC_ARB] = &slv_pmic_arb,
[SLAVE_PCNOC_CFG] = &slv_pcnoc_cfg,
[SLAVE_PRNG] = &slv_prng,
[SLAVE_QDSS_CFG] = &slv_qdss_cfg,
[SLAVE_RBCPR_CFG] = &slv_rbcpr_cfg,
[SLAVE_SDCC_1] = &slv_sdcc_1,
[SLAVE_SDCC_2] = &slv_sdcc_2,
[SLAVE_SECURITY] = &slv_security,
[SLAVE_SNOC_CFG] = &slv_snoc_cfg,
[SLAVE_SPDM] = &slv_spdm,
[SLAVE_TCSR] = &slv_tcsr,
[SLAVE_TLMM] = &slv_tlmm,
[SLAVE_USB_HS] = &slv_usb_hs,
[SLAVE_VENUS_CFG] = &slv_venus_cfg,
[SNOC_PCNOC_SLV] = &snoc_pcnoc_slv,
};
static struct msm8916_icc_desc msm8916_pcnoc = {
.nodes = msm8916_pcnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_pcnoc_nodes),
};
static int msm8916_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct msm8916_icc_provider *qp;
struct msm8916_icc_node *qn;
u64 sum_bw, max_peak_bw, rate;
u32 agg_avg = 0, agg_peak = 0;
struct icc_provider *provider;
struct icc_node *n;
int ret, i;
qn = src->data;
provider = src->provider;
qp = to_msm8916_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list)
provider->aggregate(n, 0, 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);
/* send bandwidth request 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 %d error %d\n",
qn->mas_rpm_id, 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)
return 0;
for (i = 0; i < qp->num_clks; i++) {
ret = clk_set_rate(qp->bus_clks[i].clk, rate);
if (ret) {
pr_err("%s clk_set_rate error: %d\n",
qp->bus_clks[i].id, ret);
return ret;
}
}
qn->rate = rate;
return 0;
}
static int msm8916_qnoc_probe(struct platform_device *pdev)
{
const struct msm8916_icc_desc *desc;
struct msm8916_icc_node **qnodes;
struct msm8916_icc_provider *qp;
struct device *dev = &pdev->dev;
struct icc_onecell_data *data;
struct icc_provider *provider;
struct icc_node *node;
size_t num_nodes, i;
int ret;
/* wait for the RPM proxy */
if (!qcom_icc_rpm_smd_available())
return -EPROBE_DEFER;
desc = of_device_get_match_data(dev);
if (!desc)
return -EINVAL;
qnodes = desc->nodes;
num_nodes = desc->num_nodes;
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
if (!qp)
return -ENOMEM;
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
GFP_KERNEL);
if (!data)
return -ENOMEM;
qp->bus_clks = devm_kmemdup(dev, msm8916_bus_clocks,
sizeof(msm8916_bus_clocks), GFP_KERNEL);
if (!qp->bus_clks)
return -ENOMEM;
qp->num_clks = ARRAY_SIZE(msm8916_bus_clocks);
ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
if (ret)
return ret;
ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
if (ret)
return ret;
provider = &qp->provider;
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = msm8916_icc_set;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret;
}
for (i = 0; i < num_nodes; i++) {
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);
for (j = 0; j < qnodes[i]->num_links; j++)
icc_link_create(node, qnodes[i]->links[j]);
data->nodes[i] = node;
}
data->num_nodes = num_nodes;
platform_set_drvdata(pdev, qp);
return 0;
err:
icc_nodes_remove(provider);
icc_provider_del(provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return ret;
}
static int msm8916_qnoc_remove(struct platform_device *pdev)
{
struct msm8916_icc_provider *qp = platform_get_drvdata(pdev);
icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return icc_provider_del(&qp->provider);
}
static const struct of_device_id msm8916_noc_of_match[] = {
{ .compatible = "qcom,msm8916-bimc", .data = &msm8916_bimc },
{ .compatible = "qcom,msm8916-pcnoc", .data = &msm8916_pcnoc },
{ .compatible = "qcom,msm8916-snoc", .data = &msm8916_snoc },
{ }
};
MODULE_DEVICE_TABLE(of, msm8916_noc_of_match);
static struct platform_driver msm8916_noc_driver = {
.probe = msm8916_qnoc_probe,
.remove = msm8916_qnoc_remove,
.driver = {
.name = "qnoc-msm8916",
.of_match_table = msm8916_noc_of_match,
},
};
module_platform_driver(msm8916_noc_driver);
MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
MODULE_DESCRIPTION("Qualcomm MSM8916 NoC driver");
MODULE_LICENSE("GPL v2");

View File

@ -550,15 +550,6 @@ static struct msm8974_icc_desc msm8974_snoc = {
.num_nodes = ARRAY_SIZE(msm8974_snoc_nodes),
};
static int msm8974_icc_aggregate(struct icc_node *node, u32 tag, 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 void msm8974_icc_rpm_smd_send(struct device *dev, int rsc_type,
char *name, int id, u64 val)
{
@ -603,8 +594,8 @@ static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst)
qp = to_msm8974_icc_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list)
msm8974_icc_aggregate(n, 0, n->avg_bw, n->peak_bw,
&agg_avg, &agg_peak);
provider->aggregate(n, 0, 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);
@ -652,7 +643,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct icc_onecell_data *data;
struct icc_provider *provider;
struct icc_node *node, *tmp;
struct icc_node *node;
size_t num_nodes, i;
int ret;
@ -694,7 +685,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = msm8974_icc_set;
provider->aggregate = msm8974_icc_aggregate;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
@ -732,10 +723,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
return 0;
err_del_icc:
list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
icc_node_del(node);
icc_node_destroy(node->id);
}
icc_nodes_remove(provider);
icc_provider_del(provider);
err_disable_clks:
@ -747,16 +735,10 @@ static int msm8974_icc_probe(struct platform_device *pdev)
static int msm8974_icc_remove(struct platform_device *pdev)
{
struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
struct icc_provider *provider = &qp->provider;
struct icc_node *n, *tmp;
list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
icc_node_del(n);
icc_node_destroy(n->id);
}
icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return icc_provider_del(provider);
return icc_provider_del(&qp->provider);
}
static const struct of_device_id msm8974_noc_of_match[] = {

View File

@ -327,15 +327,6 @@ static struct qcom_icc_desc qcs404_snoc = {
.num_nodes = ARRAY_SIZE(qcs404_snoc_nodes),
};
static int qcom_icc_aggregate(struct icc_node *node, u32 tag, 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;
@ -354,8 +345,8 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
qp = to_qcom_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list)
qcom_icc_aggregate(n, 0, n->avg_bw, n->peak_bw,
&agg_avg, &agg_peak);
provider->aggregate(n, 0, 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);
@ -414,7 +405,7 @@ static int qnoc_probe(struct platform_device *pdev)
struct icc_provider *provider;
struct qcom_icc_node **qnodes;
struct qcom_icc_provider *qp;
struct icc_node *node, *tmp;
struct icc_node *node;
size_t num_nodes, i;
int ret;
@ -456,7 +447,7 @@ static int qnoc_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev;
provider->set = qcom_icc_set;
provider->aggregate = qcom_icc_aggregate;
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
@ -494,10 +485,7 @@ static int qnoc_probe(struct platform_device *pdev)
return 0;
err:
list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
icc_node_del(node);
icc_node_destroy(node->id);
}
icc_nodes_remove(provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(provider);
@ -507,16 +495,10 @@ static int qnoc_probe(struct platform_device *pdev)
static int qnoc_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
struct icc_provider *provider = &qp->provider;
struct icc_node *n, *tmp;
list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
icc_node_del(n);
icc_node_destroy(n->id);
}
icc_nodes_remove(&qp->provider);
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return icc_provider_del(provider);
return icc_provider_del(&qp->provider);
}
static const struct of_device_id qcs404_noc_of_match[] = {

View File

@ -855,11 +855,7 @@ static int qnoc_probe(struct platform_device *pdev)
return ret;
err:
list_for_each_entry(node, &provider->nodes, node_list) {
icc_node_del(node);
icc_node_destroy(node->id);
}
icc_nodes_remove(provider);
icc_provider_del(provider);
return ret;
}
@ -867,15 +863,9 @@ static int qnoc_probe(struct platform_device *pdev)
static int qnoc_remove(struct platform_device *pdev)
{
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
struct icc_provider *provider = &qp->provider;
struct icc_node *n, *tmp;
list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
icc_node_del(n);
icc_node_destroy(n->id);
}
return icc_provider_del(provider);
icc_nodes_remove(&qp->provider);
return icc_provider_del(&qp->provider);
}
static const struct of_device_id qnoc_of_match[] = {

View File

@ -0,0 +1,88 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Interconnect framework tracepoints
* Copyright (c) 2019, Linaro Ltd.
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM interconnect
#if !defined(_TRACE_INTERCONNECT_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_INTERCONNECT_H
#include <linux/interconnect.h>
#include <linux/tracepoint.h>
TRACE_EVENT(icc_set_bw,
TP_PROTO(struct icc_path *p, struct icc_node *n, int i,
u32 avg_bw, u32 peak_bw),
TP_ARGS(p, n, i, avg_bw, peak_bw),
TP_STRUCT__entry(
__string(path_name, p->name)
__string(dev, dev_name(p->reqs[i].dev))
__string(node_name, n->name)
__field(u32, avg_bw)
__field(u32, peak_bw)
__field(u32, node_avg_bw)
__field(u32, node_peak_bw)
),
TP_fast_assign(
__assign_str(path_name, p->name);
__assign_str(dev, dev_name(p->reqs[i].dev));
__assign_str(node_name, n->name);
__entry->avg_bw = avg_bw;
__entry->peak_bw = peak_bw;
__entry->node_avg_bw = n->avg_bw;
__entry->node_peak_bw = n->peak_bw;
),
TP_printk("path=%s dev=%s node=%s avg_bw=%u peak_bw=%u agg_avg=%u agg_peak=%u",
__get_str(path_name),
__get_str(dev),
__get_str(node_name),
__entry->avg_bw,
__entry->peak_bw,
__entry->node_avg_bw,
__entry->node_peak_bw)
);
TRACE_EVENT(icc_set_bw_end,
TP_PROTO(struct icc_path *p, int ret),
TP_ARGS(p, ret),
TP_STRUCT__entry(
__string(path_name, p->name)
__string(dev, dev_name(p->reqs[0].dev))
__field(int, ret)
),
TP_fast_assign(
__assign_str(path_name, p->name);
__assign_str(dev, dev_name(p->reqs[0].dev));
__entry->ret = ret;
),
TP_printk("path=%s dev=%s ret=%d",
__get_str(path_name),
__get_str(dev),
__entry->ret)
);
#endif /* _TRACE_INTERCONNECT_H */
/* This part must be outside protection */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>

View File

@ -0,0 +1,100 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Qualcomm interconnect IDs
*
* Copyright (c) 2019, Linaro Ltd.
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_MSM8916_H
#define __DT_BINDINGS_INTERCONNECT_QCOM_MSM8916_H
#define BIMC_SNOC_SLV 0
#define MASTER_JPEG 1
#define MASTER_MDP_PORT0 2
#define MASTER_QDSS_BAM 3
#define MASTER_QDSS_ETR 4
#define MASTER_SNOC_CFG 5
#define MASTER_VFE 6
#define MASTER_VIDEO_P0 7
#define SNOC_MM_INT_0 8
#define SNOC_MM_INT_1 9
#define SNOC_MM_INT_2 10
#define SNOC_MM_INT_BIMC 11
#define PCNOC_SNOC_SLV 12
#define SLAVE_APSS 13
#define SLAVE_CATS_128 14
#define SLAVE_OCMEM_64 15
#define SLAVE_IMEM 16
#define SLAVE_QDSS_STM 17
#define SLAVE_SRVC_SNOC 18
#define SNOC_BIMC_0_MAS 19
#define SNOC_BIMC_1_MAS 20
#define SNOC_INT_0 21
#define SNOC_INT_1 22
#define SNOC_INT_BIMC 23
#define SNOC_PCNOC_MAS 24
#define SNOC_QDSS_INT 25
#define BIMC_SNOC_MAS 0
#define MASTER_AMPSS_M0 1
#define MASTER_GRAPHICS_3D 2
#define MASTER_TCU0 3
#define MASTER_TCU1 4
#define SLAVE_AMPSS_L2 5
#define SLAVE_EBI_CH0 6
#define SNOC_BIMC_0_SLV 7
#define SNOC_BIMC_1_SLV 8
#define MASTER_BLSP_1 0
#define MASTER_DEHR 1
#define MASTER_LPASS 2
#define MASTER_CRYPTO_CORE0 3
#define MASTER_SDCC_1 4
#define MASTER_SDCC_2 5
#define MASTER_SPDM 6
#define MASTER_USB_HS 7
#define PCNOC_INT_0 8
#define PCNOC_INT_1 9
#define PCNOC_MAS_0 10
#define PCNOC_MAS_1 11
#define PCNOC_SLV_0 12
#define PCNOC_SLV_1 13
#define PCNOC_SLV_2 14
#define PCNOC_SLV_3 15
#define PCNOC_SLV_4 16
#define PCNOC_SLV_8 17
#define PCNOC_SLV_9 18
#define PCNOC_SNOC_MAS 19
#define SLAVE_BIMC_CFG 20
#define SLAVE_BLSP_1 21
#define SLAVE_BOOT_ROM 22
#define SLAVE_CAMERA_CFG 23
#define SLAVE_CLK_CTL 24
#define SLAVE_CRYPTO_0_CFG 25
#define SLAVE_DEHR_CFG 26
#define SLAVE_DISPLAY_CFG 27
#define SLAVE_GRAPHICS_3D_CFG 28
#define SLAVE_IMEM_CFG 29
#define SLAVE_LPASS 30
#define SLAVE_MPM 31
#define SLAVE_MSG_RAM 32
#define SLAVE_MSS 33
#define SLAVE_PDM 34
#define SLAVE_PMIC_ARB 35
#define SLAVE_PCNOC_CFG 36
#define SLAVE_PRNG 37
#define SLAVE_QDSS_CFG 38
#define SLAVE_RBCPR_CFG 39
#define SLAVE_SDCC_1 40
#define SLAVE_SDCC_2 41
#define SLAVE_SECURITY 42
#define SLAVE_SNOC_CFG 43
#define SLAVE_SPDM 44
#define SLAVE_TCSR 45
#define SLAVE_TLMM 46
#define SLAVE_USB_HS 47
#define SLAVE_VENUS_CFG 48
#define SNOC_PCNOC_SLV 49
#endif

View File

@ -92,17 +92,26 @@ struct icc_node {
#if IS_ENABLED(CONFIG_INTERCONNECT)
int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
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_nodes_remove(struct icc_provider *provider);
int icc_provider_add(struct icc_provider *provider);
int icc_provider_del(struct icc_provider *provider);
#else
static inline int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
return -ENOTSUPP;
}
static inline struct icc_node *icc_node_create(int id)
{
return ERR_PTR(-ENOTSUPP);
@ -130,6 +139,11 @@ void icc_node_del(struct icc_node *node)
{
}
static inline int icc_nodes_remove(struct icc_provider *provider)
{
return -ENOTSUPP;
}
static inline int icc_provider_add(struct icc_provider *provider)
{
return -ENOTSUPP;