Add samsung specific changes
This commit is contained in:
@@ -11,6 +11,16 @@ menuconfig INTERCONNECT
|
||||
|
||||
if INTERCONNECT
|
||||
|
||||
menuconfig INTERCONNECT_TEST
|
||||
tristate "Debugfs test"
|
||||
depends on DEBUG_FS
|
||||
help
|
||||
Expose the interconnect API to userspace for testing purposes. This
|
||||
will create /sys/kernel/debug/interconnect-test to allow requesting
|
||||
bandwidth between endpoints.
|
||||
|
||||
If unsure, say no.
|
||||
|
||||
source "drivers/interconnect/imx/Kconfig"
|
||||
source "drivers/interconnect/qcom/Kconfig"
|
||||
source "drivers/interconnect/samsung/Kconfig"
|
||||
|
@@ -2,8 +2,10 @@
|
||||
|
||||
CFLAGS_core.o := -I$(src)
|
||||
icc-core-objs := core.o bulk.o debugfs-client.o
|
||||
icc-test-objs := debugfs-test.o
|
||||
|
||||
obj-$(CONFIG_INTERCONNECT) += icc-core.o
|
||||
obj-$(CONFIG_INTERCONNECT_TEST) += icc-test.o
|
||||
obj-$(CONFIG_INTERCONNECT_IMX) += imx/
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/
|
||||
obj-$(CONFIG_INTERCONNECT_SAMSUNG) += samsung/
|
||||
|
115
drivers/interconnect/debugfs-test.c
Normal file
115
drivers/interconnect/debugfs-test.c
Normal file
@@ -0,0 +1,115 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2017, Linaro Ltd.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static struct platform_device *icc_pdev;
|
||||
static struct dentry *debugfs_dir;
|
||||
static struct icc_path *path;
|
||||
static u32 src_port;
|
||||
static u32 dst_port;
|
||||
|
||||
static u32 avg_bw;
|
||||
static u32 peak_bw;
|
||||
|
||||
static ssize_t get_write_op(struct file *file, char const __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoul_from_user(buf, count, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
path = icc_get(&icc_pdev->dev, src_port, dst_port);
|
||||
if (IS_ERR(path))
|
||||
return PTR_ERR(path);
|
||||
|
||||
*ppos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations get_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = get_write_op
|
||||
};
|
||||
|
||||
static ssize_t commit_write_op(struct file *file, char const __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoul_from_user(buf, count, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (IS_ERR(path))
|
||||
return PTR_ERR(path);
|
||||
|
||||
ret = icc_set_bw(path, avg_bw, peak_bw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*ppos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations commit_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = commit_write_op
|
||||
};
|
||||
|
||||
static void __exit icc_test_exit(void)
|
||||
{
|
||||
if (!IS_ERR(path))
|
||||
icc_put(path);
|
||||
|
||||
debugfs_remove_recursive(debugfs_dir);
|
||||
platform_device_del(icc_pdev);
|
||||
platform_device_put(icc_pdev);
|
||||
}
|
||||
|
||||
static int __init icc_test_init(void)
|
||||
{
|
||||
icc_pdev = platform_device_alloc("icc-test", PLATFORM_DEVID_AUTO);
|
||||
platform_device_add(icc_pdev);
|
||||
|
||||
debugfs_dir = debugfs_create_dir("interconnect-test", NULL);
|
||||
if (!debugfs_dir)
|
||||
pr_err("interconnect: error creating debugfs directory\n");
|
||||
|
||||
debugfs_create_u32("src_port", 0600, debugfs_dir, &src_port);
|
||||
debugfs_create_u32("dst_port", 0600, debugfs_dir, &dst_port);
|
||||
debugfs_create_file("get", 0200, debugfs_dir, NULL, &get_fops);
|
||||
debugfs_create_u32("avg_bw", 0600, debugfs_dir, &avg_bw);
|
||||
debugfs_create_u32("peak_bw", 0600, debugfs_dir, &peak_bw);
|
||||
debugfs_create_file("commit", 0200, debugfs_dir, NULL, &commit_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(icc_test_init);
|
||||
module_exit(icc_test_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#endif
|
@@ -8,6 +8,21 @@ config INTERCONNECT_QCOM
|
||||
config INTERCONNECT_QCOM_BCM_VOTER
|
||||
tristate
|
||||
|
||||
config INTERCONNECT_QCOM_QOS_RPM
|
||||
tristate
|
||||
|
||||
config INTERCONNECT_QCOM_MONACO
|
||||
tristate "MONACO interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on MSM_RPM_SMD
|
||||
select INTERCONNECT_QCOM_RPM
|
||||
select INTERCONNECT_QCOM_QOS_RPM
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on monaco-based platforms. The interconnect provider collects and
|
||||
aggreagates the cosumer bandwidth requests to satisfy constraints
|
||||
placed on Network-on-Chip performance states.
|
||||
|
||||
config INTERCONNECT_QCOM_MSM8916
|
||||
tristate "Qualcomm MSM8916 interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
@@ -182,6 +197,19 @@ config INTERCONNECT_QCOM_SDX65
|
||||
This is a driver for the Qualcomm Network-on-Chip on sdx65-based
|
||||
platforms.
|
||||
|
||||
config INTERCONNECT_QCOM_SDX75
|
||||
tristate "SDX75 interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on OF
|
||||
select INTERCONNECT_QCOM_BCM_VOTER
|
||||
select INTERCONNECT_QCOM_RPMH
|
||||
select INTERCONNECT_QCOM_QOS
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on sdx75-based platforms. Interconnect driver provides interfaces
|
||||
for setting bandwidth between two endpoints (path). It also used to
|
||||
configure NOC QoS settings (Quality of Service).
|
||||
|
||||
config INTERCONNECT_QCOM_SM6350
|
||||
tristate "Qualcomm SM6350 interconnect driver"
|
||||
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
|
||||
@@ -227,6 +255,45 @@ config INTERCONNECT_QCOM_SM8450
|
||||
This is a driver for the Qualcomm Network-on-Chip on SM8450-based
|
||||
platforms.
|
||||
|
||||
config INTERCONNECT_QCOM_SUN
|
||||
tristate "SUN interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on OF
|
||||
select INTERCONNECT_QCOM_BCM_VOTER
|
||||
select INTERCONNECT_QCOM_RPMH
|
||||
select INTERCONNECT_QCOM_QOS
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on Sun-based platforms. Interconnect driver provides interfaces
|
||||
for setting bandwidth between two endpoints (path). It also used to
|
||||
configure NOC QoS settings (Quality of Service).
|
||||
|
||||
config INTERCONNECT_QCOM_TUNA
|
||||
tristate "TUNA interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on OF
|
||||
select INTERCONNECT_QCOM_BCM_VOTER
|
||||
select INTERCONNECT_QCOM_RPMH
|
||||
select INTERCONNECT_QCOM_QOS
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on Tuna-based platforms. Interconnect driver provides interfaces
|
||||
for setting bandwidth between two endpoints (path). It also used to
|
||||
configure NOC QoS settings (Quality of Service).
|
||||
|
||||
config INTERCONNECT_QCOM_PINEAPPLE
|
||||
tristate "PINEAPPLE interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on OF
|
||||
select INTERCONNECT_QCOM_BCM_VOTER
|
||||
select INTERCONNECT_QCOM_RPMH
|
||||
select INTERCONNECT_QCOM_QOS
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on Pineapple-based platforms. Interconnect driver provides interfaces
|
||||
for setting bandwidth between two endpoints (path). It also used to
|
||||
configure NOC QoS settings (Quality of Service).
|
||||
|
||||
config INTERCONNECT_QCOM_SM8550
|
||||
tristate "Qualcomm SM8550 interconnect driver"
|
||||
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
|
||||
@@ -236,5 +303,46 @@ config INTERCONNECT_QCOM_SM8550
|
||||
This is a driver for the Qualcomm Network-on-Chip on SM8550-based
|
||||
platforms.
|
||||
|
||||
config INTERCONNECT_QCOM_PARROT
|
||||
tristate "PARROT interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on QCOM_RPMH && QCOM_COMMAND_DB && OF
|
||||
select INTERCONNECT_QCOM_BCM_VOTER
|
||||
select INTERCONNECT_QCOM_RPMH
|
||||
select INTERCONNECT_QCOM_QOS
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on Parrot-based platforms. Interconnect driver provides interfaces
|
||||
for setting bandwidth between two endpoints (path). It also used to
|
||||
configure NOC QoS settings (Quality of Service).
|
||||
|
||||
config INTERCONNECT_QCOM_RPM
|
||||
tristate
|
||||
|
||||
config INTERCONNECT_QCOM_SMD_RPM
|
||||
tristate
|
||||
|
||||
config INTERCONNECT_QCOM_QOS
|
||||
tristate
|
||||
|
||||
config INTERCONNECT_QCOM_DEBUG
|
||||
tristate "QCOM-specific interconnect debug features"
|
||||
depends on INTERCONNECT_QCOM
|
||||
help
|
||||
This driver provides debug features specific to
|
||||
Qualcomm Technologies, Inc. interconnect drivers. These features
|
||||
include optionally printing all enabled interconnect votes when
|
||||
entering suspend.
|
||||
|
||||
config INTERCONNECT_QCOM_RAVELIN
|
||||
tristate "RAVELIN interconnect driver"
|
||||
depends on INTERCONNECT_QCOM
|
||||
depends on QCOM_RPMH && QCOM_COMMAND_DB && OF
|
||||
select INTERCONNECT_QCOM_BCM_VOTER
|
||||
select INTERCONNECT_QCOM_RPMH
|
||||
select INTERCONNECT_QCOM_QOS
|
||||
help
|
||||
This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
|
||||
on Ravelin-based platforms. Interconnect driver provides interfaces
|
||||
for setting bandwidth between two endpoints (path). It also used to
|
||||
configure NOC QoS settings (Quality of Service).
|
||||
|
@@ -9,10 +9,12 @@ qnoc-msm8939-objs := msm8939.o
|
||||
qnoc-msm8974-objs := msm8974.o
|
||||
qnoc-msm8996-objs := msm8996.o
|
||||
icc-osm-l3-objs := osm-l3.o
|
||||
qnoc-monaco-objs := monaco.o
|
||||
qnoc-qcm2290-objs := qcm2290.o
|
||||
qnoc-qcs404-objs := qcs404.o
|
||||
qnoc-qdu1000-objs := qdu1000.o
|
||||
icc-rpmh-obj := icc-rpmh.o
|
||||
icc-rpm-obj := icc-rpm.o
|
||||
qnoc-sa8775p-objs := sa8775p.o
|
||||
qnoc-sc7180-objs := sc7180.o
|
||||
qnoc-sc7280-objs := sc7280.o
|
||||
@@ -23,13 +25,21 @@ qnoc-sdm670-objs := sdm670.o
|
||||
qnoc-sdm845-objs := sdm845.o
|
||||
qnoc-sdx55-objs := sdx55.o
|
||||
qnoc-sdx65-objs := sdx65.o
|
||||
qnoc-sdx75-objs := sdx75.o
|
||||
qnoc-sm6350-objs := sm6350.o
|
||||
qnoc-sm8150-objs := sm8150.o
|
||||
qnoc-sm8250-objs := sm8250.o
|
||||
qnoc-sm8350-objs := sm8350.o
|
||||
qnoc-sm8450-objs := sm8450.o
|
||||
qnoc-sun-objs := sun.o
|
||||
qnoc-tuna-objs := tuna.o
|
||||
qnoc-pineapple-objs := pineapple.o
|
||||
qnoc-sm8550-objs := sm8550.o
|
||||
icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o
|
||||
qnoc-parrot-objs := parrot.o
|
||||
qnoc-ravelin-objs := ravelin.o
|
||||
icc-smd-rpm-objs := smd-rpm.o
|
||||
qnoc-qos-rpm-obj := qnoc-qos-rpm.o
|
||||
qnoc-qos-obj := qnoc-qos.o
|
||||
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
|
||||
@@ -37,10 +47,12 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_MONACO) += qnoc-monaco.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QDU1000) += qnoc-qdu1000.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_RPM) += icc-rpm.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SA8775P) += qnoc-sa8775p.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o
|
||||
@@ -51,10 +63,19 @@ obj-$(CONFIG_INTERCONNECT_QCOM_SDM670) += qnoc-sdm670.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SDX55) += qnoc-sdx55.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SDX65) += qnoc-sdx65.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SDX75) += qnoc-sdx75.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SM6350) += qnoc-sm6350.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SM8150) += qnoc-sm8150.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SM8250) += qnoc-sm8250.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SM8350) += qnoc-sm8350.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SM8450) += qnoc-sm8450.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SUN) += qnoc-sun.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_TUNA) += qnoc-tuna.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_PINEAPPLE) += qnoc-pineapple.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SM8550) += qnoc-sm8550.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_PARROT) += qnoc-parrot.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_RAVELIN) += qnoc-ravelin.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += icc-smd-rpm.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QOS) += qnoc-qos.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_QOS_RPM) += qnoc-qos-rpm.o
|
||||
obj-$(CONFIG_INTERCONNECT_QCOM_DEBUG) += icc-debug.o
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <asm/div64.h>
|
||||
@@ -16,6 +17,9 @@
|
||||
#include "bcm-voter.h"
|
||||
#include "icc-rpmh.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
||||
|
||||
static LIST_HEAD(bcm_voters);
|
||||
static DEFINE_MUTEX(bcm_voter_lock);
|
||||
|
||||
@@ -28,15 +32,18 @@ static DEFINE_MUTEX(bcm_voter_lock);
|
||||
* @ws_list: list containing bcms that have different wake/sleep votes
|
||||
* @voter_node: list of bcm voters
|
||||
* @tcs_wait: mask for which buckets require TCS completion
|
||||
* @has_amc: flag to determine if this voter supports AMC
|
||||
*/
|
||||
struct bcm_voter {
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
struct qcom_icc_crm_voter *crm;
|
||||
struct mutex lock;
|
||||
struct list_head commit_list;
|
||||
struct list_head ws_list;
|
||||
struct list_head voter_node;
|
||||
u32 tcs_wait;
|
||||
bool has_amc;
|
||||
};
|
||||
|
||||
static int cmp_vcd(void *priv, const struct list_head *a, const struct list_head *b)
|
||||
@@ -72,19 +79,17 @@ static void bcm_aggregate_mask(struct qcom_icc_bcm *bcm)
|
||||
node = bcm->nodes[i];
|
||||
|
||||
/* If any vote in this bucket exists, keep the BCM enabled */
|
||||
if (node->sum_avg[bucket] || node->max_peak[bucket]) {
|
||||
bcm->vote_x[bucket] = 0;
|
||||
bcm->vote_y[bucket] = bcm->enable_mask;
|
||||
break;
|
||||
}
|
||||
if (node->sum_avg[bucket] || node->max_peak[bucket])
|
||||
bcm->vote_y[bucket] |= bcm->enable_mask;
|
||||
|
||||
if (node->perf_mode[bucket])
|
||||
bcm->vote_y[bucket] |= bcm->perf_mode_mask;
|
||||
}
|
||||
}
|
||||
|
||||
if (bcm->keepalive) {
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_AMC] = bcm->enable_mask;
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = bcm->enable_mask;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_AMC] = bcm->enable_mask;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = bcm->enable_mask;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_AMC] |= bcm->enable_mask;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] |= bcm->enable_mask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +245,31 @@ struct bcm_voter *of_bcm_voter_get(struct device *dev, const char *name)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_bcm_voter_get);
|
||||
|
||||
/**
|
||||
* qcom_icc_bcm_voter_exist - checks if the bcm voter exists
|
||||
* @voter: voter that needs to checked against available bcm voters
|
||||
*
|
||||
* Returns true incase bcm_voter exists else false
|
||||
*/
|
||||
static bool qcom_icc_bcm_voter_exist(struct bcm_voter *voter)
|
||||
{
|
||||
bool exists = false;
|
||||
struct bcm_voter *temp;
|
||||
|
||||
if (voter) {
|
||||
mutex_lock(&bcm_voter_lock);
|
||||
list_for_each_entry(temp, &bcm_voters, voter_node) {
|
||||
if (temp == voter) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bcm_voter_lock);
|
||||
}
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_icc_bcm_voter_add - queues up the bcm nodes that require updates
|
||||
* @voter: voter that the bcms are being added to
|
||||
@@ -250,6 +280,9 @@ void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm)
|
||||
if (!voter)
|
||||
return;
|
||||
|
||||
if (!qcom_icc_bcm_voter_exist(voter))
|
||||
return;
|
||||
|
||||
mutex_lock(&voter->lock);
|
||||
if (list_empty(&bcm->list))
|
||||
list_add_tail(&bcm->list, &voter->commit_list);
|
||||
@@ -261,6 +294,194 @@ void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_add);
|
||||
|
||||
static void qcom_icc_bcm_log(struct bcm_voter *voter, enum rpmh_state state,
|
||||
const struct tcs_cmd *cmd, const u32 *commit_idx)
|
||||
{
|
||||
static const char * const rpmh_state[] = {
|
||||
"RPMH_SLEEP_STATE",
|
||||
"RPMH_WAKE_ONLY_STATE",
|
||||
"RPMH_ACTIVE_ONLY_STATE"
|
||||
};
|
||||
int i, count = 0;
|
||||
|
||||
if (!cmd || !commit_idx)
|
||||
return;
|
||||
|
||||
while (commit_idx[count] > 0)
|
||||
count++;
|
||||
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
trace_bcm_voter_commit(rpmh_state[state], cmd);
|
||||
}
|
||||
|
||||
static int commit_rpmh(struct bcm_voter *voter)
|
||||
{
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct qcom_icc_bcm *bcm_tmp;
|
||||
int commit_idx[MAX_VCD + 1];
|
||||
struct tcs_cmd cmds[MAX_BCMS];
|
||||
int ret = 0;
|
||||
|
||||
if (voter->has_amc) {
|
||||
/*
|
||||
* Pre sort the BCMs based on VCD for ease of generating a command list
|
||||
* that groups the BCMs with the same VCD together. VCDs are numbered
|
||||
* with lowest being the most expensive time wise, ensuring that
|
||||
* those commands are being sent the earliest in the queue. This needs
|
||||
* to be sorted every commit since we can't guarantee the order in which
|
||||
* the BCMs are added to the list.
|
||||
*/
|
||||
list_sort(NULL, &voter->commit_list, cmp_vcd);
|
||||
|
||||
/*
|
||||
* Construct the command list based on a pre ordered list of BCMs
|
||||
* based on VCD.
|
||||
*/
|
||||
tcs_list_gen(voter, QCOM_ICC_BUCKET_AMC, cmds, commit_idx);
|
||||
if (!commit_idx[0])
|
||||
goto out;
|
||||
|
||||
qcom_icc_bcm_log(voter, RPMH_ACTIVE_ONLY_STATE, cmds, commit_idx);
|
||||
ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE,
|
||||
cmds, commit_idx);
|
||||
|
||||
/*
|
||||
* Ignore -EBUSY for AMC requests, since this can only happen for AMC
|
||||
* requests when the RSC is in solver mode. We can only be in solver
|
||||
* mode at the time of request for secondary RSCs (e.g. Display RSC),
|
||||
* since the primary Apps RSC is only in solver mode while
|
||||
* entering/exiting power collapse when SW isn't running. The -EBUSY
|
||||
* response is expected in solver and is a non-issue, since we just
|
||||
* want the request to apply to the WAKE set in that case instead.
|
||||
* Interconnect doesn't know when the RSC is in solver, so just always
|
||||
* send AMC and ignore the harmless error response.
|
||||
*/
|
||||
if (ret && ret != -EBUSY) {
|
||||
pr_err("Error sending AMC RPMH requests (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rpmh_invalidate(voter->dev);
|
||||
|
||||
list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list)
|
||||
list_del_init(&bcm->list);
|
||||
|
||||
list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) {
|
||||
/*
|
||||
* Only generate WAKE and SLEEP commands if a resource's
|
||||
* requirements change as the execution environment transitions
|
||||
* between different power states.
|
||||
*/
|
||||
if (!voter->has_amc ||
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_WAKE] != bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] ||
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] != bcm->vote_y[QCOM_ICC_BUCKET_SLEEP])
|
||||
list_add_tail(&bcm->list, &voter->commit_list);
|
||||
else
|
||||
list_del_init(&bcm->ws_list);
|
||||
}
|
||||
|
||||
if (list_empty(&voter->commit_list))
|
||||
goto out;
|
||||
|
||||
list_sort(NULL, &voter->commit_list, cmp_vcd);
|
||||
|
||||
tcs_list_gen(voter, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx);
|
||||
qcom_icc_bcm_log(voter, RPMH_WAKE_ONLY_STATE, cmds, commit_idx);
|
||||
|
||||
ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx);
|
||||
if (ret) {
|
||||
pr_err("Error sending WAKE RPMH requests (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tcs_list_gen(voter, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx);
|
||||
qcom_icc_bcm_log(voter, RPMH_SLEEP_STATE, cmds, commit_idx);
|
||||
|
||||
ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx);
|
||||
if (ret) {
|
||||
pr_err("Error sending SLEEP RPMH requests (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int map_crm_pwr_state(enum crm_drv_type client_type, u32 bucket)
|
||||
{
|
||||
if (client_type == CRM_HW_DRV)
|
||||
return bucket;
|
||||
|
||||
switch (bucket) {
|
||||
case QCOM_ICC_BUCKET_AMC: return CRM_ACTIVE_STATE;
|
||||
case QCOM_ICC_BUCKET_WAKE: return CRM_WAKE_STATE;
|
||||
case QCOM_ICC_BUCKET_SLEEP: return CRM_SLEEP_STATE;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int crm_cmd_gen(struct crm_cmd *cmd, enum crm_drv_type client_type,
|
||||
u32 bucket, u32 node, u64 vote_x, u64 vote_y)
|
||||
{
|
||||
int pwr_state;
|
||||
|
||||
if (!cmd)
|
||||
return -EINVAL;
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
||||
if (vote_x > BCM_TCS_CMD_VOTE_MASK)
|
||||
vote_x = BCM_TCS_CMD_VOTE_MASK;
|
||||
|
||||
if (vote_y > BCM_TCS_CMD_VOTE_MASK)
|
||||
vote_y = BCM_TCS_CMD_VOTE_MASK;
|
||||
|
||||
pwr_state = map_crm_pwr_state(client_type, bucket);
|
||||
if (pwr_state < 0)
|
||||
return pwr_state;
|
||||
|
||||
cmd->pwr_state.hw = pwr_state;
|
||||
cmd->resource_idx = node;
|
||||
cmd->data = BCM_TCS_CMD(true, true, vote_x, vote_y);
|
||||
cmd->wait = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int commit_crm(struct bcm_voter *voter)
|
||||
{
|
||||
struct list_head *bcm_list = &voter->commit_list;
|
||||
struct qcom_icc_crm_voter *crm = voter->crm;
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct crm_cmd crm_cmd;
|
||||
int ret, i;
|
||||
|
||||
list_for_each_entry(bcm, bcm_list, list) {
|
||||
for (i = 0; i < crm->pwr_states; i++) {
|
||||
ret = crm_cmd_gen(&crm_cmd, crm->client_type, i, bcm->crm_node,
|
||||
bcm->vote_x[i], bcm->vote_y[i]);
|
||||
if (ret) {
|
||||
pr_err("Error generating crm_cmd: ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = crm_write_bw_pt_vote(crm->dev, crm->client_type,
|
||||
crm->client_idx, &crm_cmd);
|
||||
if (ret) {
|
||||
pr_err("Error writing crm bw: ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_icc_bcm_voter_commit - generates and commits tcs cmds based on bcms
|
||||
* @voter: voter that needs flushing
|
||||
@@ -277,88 +498,28 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
|
||||
{
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct qcom_icc_bcm *bcm_tmp;
|
||||
int commit_idx[MAX_VCD + 1];
|
||||
struct tcs_cmd cmds[MAX_BCMS];
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (!voter)
|
||||
return 0;
|
||||
|
||||
if (!qcom_icc_bcm_voter_exist(voter))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&voter->lock);
|
||||
|
||||
list_for_each_entry(bcm, &voter->commit_list, list) {
|
||||
if (bcm->enable_mask)
|
||||
if (bcm->type == QCOM_ICC_BCM_TYPE_MASK || bcm->enable_mask)
|
||||
bcm_aggregate_mask(bcm);
|
||||
else
|
||||
bcm_aggregate(bcm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre sort the BCMs based on VCD for ease of generating a command list
|
||||
* that groups the BCMs with the same VCD together. VCDs are numbered
|
||||
* with lowest being the most expensive time wise, ensuring that
|
||||
* those commands are being sent the earliest in the queue. This needs
|
||||
* to be sorted every commit since we can't guarantee the order in which
|
||||
* the BCMs are added to the list.
|
||||
*/
|
||||
list_sort(NULL, &voter->commit_list, cmp_vcd);
|
||||
if (voter->crm)
|
||||
ret = commit_crm(voter);
|
||||
else
|
||||
ret = commit_rpmh(voter);
|
||||
|
||||
/*
|
||||
* Construct the command list based on a pre ordered list of BCMs
|
||||
* based on VCD.
|
||||
*/
|
||||
tcs_list_gen(voter, QCOM_ICC_BUCKET_AMC, cmds, commit_idx);
|
||||
if (!commit_idx[0])
|
||||
goto out;
|
||||
|
||||
rpmh_invalidate(voter->dev);
|
||||
|
||||
ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE,
|
||||
cmds, commit_idx);
|
||||
if (ret) {
|
||||
pr_err("Error sending AMC RPMH requests (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list)
|
||||
list_del_init(&bcm->list);
|
||||
|
||||
list_for_each_entry_safe(bcm, bcm_tmp, &voter->ws_list, ws_list) {
|
||||
/*
|
||||
* Only generate WAKE and SLEEP commands if a resource's
|
||||
* requirements change as the execution environment transitions
|
||||
* between different power states.
|
||||
*/
|
||||
if (bcm->vote_x[QCOM_ICC_BUCKET_WAKE] !=
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_SLEEP] ||
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] !=
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_SLEEP])
|
||||
list_add_tail(&bcm->list, &voter->commit_list);
|
||||
else
|
||||
list_del_init(&bcm->ws_list);
|
||||
}
|
||||
|
||||
if (list_empty(&voter->commit_list))
|
||||
goto out;
|
||||
|
||||
list_sort(NULL, &voter->commit_list, cmp_vcd);
|
||||
|
||||
tcs_list_gen(voter, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx);
|
||||
|
||||
ret = rpmh_write_batch(voter->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx);
|
||||
if (ret) {
|
||||
pr_err("Error sending WAKE RPMH requests (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tcs_list_gen(voter, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx);
|
||||
|
||||
ret = rpmh_write_batch(voter->dev, RPMH_SLEEP_STATE, cmds, commit_idx);
|
||||
if (ret) {
|
||||
pr_err("Error sending SLEEP RPMH requests (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
list_for_each_entry_safe(bcm, bcm_tmp, &voter->commit_list, list)
|
||||
list_del_init(&bcm->list);
|
||||
|
||||
@@ -370,7 +531,10 @@ EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_commit);
|
||||
static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct qcom_icc_crm_voter *crm;
|
||||
struct bcm_voter *voter;
|
||||
const char *crm_name;
|
||||
int ret;
|
||||
|
||||
voter = devm_kzalloc(&pdev->dev, sizeof(*voter), GFP_KERNEL);
|
||||
if (!voter)
|
||||
@@ -378,6 +542,7 @@ static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
|
||||
|
||||
voter->dev = &pdev->dev;
|
||||
voter->np = np;
|
||||
voter->has_amc = !of_property_read_bool(np, "qcom,no-amc");
|
||||
|
||||
if (of_property_read_u32(np, "qcom,tcs-wait", &voter->tcs_wait))
|
||||
voter->tcs_wait = QCOM_ICC_TAG_ACTIVE_ONLY;
|
||||
@@ -386,6 +551,42 @@ static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
|
||||
INIT_LIST_HEAD(&voter->commit_list);
|
||||
INIT_LIST_HEAD(&voter->ws_list);
|
||||
|
||||
ret = of_property_read_string(np, "qcom,crm-name", &crm_name);
|
||||
if (!ret) {
|
||||
crm = devm_kzalloc(&pdev->dev, sizeof(*crm), GFP_KERNEL);
|
||||
if (!crm)
|
||||
return -ENOMEM;
|
||||
|
||||
crm->dev = crm_get_device(crm_name);
|
||||
if (IS_ERR(crm->dev)) {
|
||||
if (PTR_ERR(crm->dev) == -ENODEV) {
|
||||
dev_err(&pdev->dev, "crm_name=%s unavailable=%d\n",
|
||||
crm_name, -EPROBE_DEFER);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
return PTR_ERR(crm->dev);
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "qcom,crm-sw-client"))
|
||||
crm->client_type = CRM_SW_DRV;
|
||||
else
|
||||
crm->client_type = CRM_HW_DRV;
|
||||
|
||||
ret = of_property_read_u32(np, "qcom,crm-client-idx", &crm->client_idx);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Error getting crm-client-idx, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "qcom,crm-pwr-states", &crm->pwr_states);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Error getting crm-pwr-states, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
voter->crm = crm;
|
||||
}
|
||||
|
||||
mutex_lock(&bcm_voter_lock);
|
||||
list_add_tail(&voter->voter_node, &bcm_voters);
|
||||
mutex_unlock(&bcm_voter_lock);
|
||||
@@ -393,6 +594,23 @@ static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_icc_bcm_voter_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct bcm_voter *voter, *temp;
|
||||
|
||||
mutex_lock(&bcm_voter_lock);
|
||||
list_for_each_entry_safe(voter, temp, &bcm_voters, voter_node) {
|
||||
if (voter->np == np) {
|
||||
list_del(&voter->voter_node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bcm_voter_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm_voter_of_match[] = {
|
||||
{ .compatible = "qcom,bcm-voter" },
|
||||
{ }
|
||||
@@ -401,12 +619,18 @@ MODULE_DEVICE_TABLE(of, bcm_voter_of_match);
|
||||
|
||||
static struct platform_driver qcom_icc_bcm_voter_driver = {
|
||||
.probe = qcom_icc_bcm_voter_probe,
|
||||
.remove = qcom_icc_bcm_voter_remove,
|
||||
.driver = {
|
||||
.name = "bcm_voter",
|
||||
.of_match_table = bcm_voter_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(qcom_icc_bcm_voter_driver);
|
||||
|
||||
static int __init qcom_icc_bcm_voter_driver_init(void)
|
||||
{
|
||||
return platform_driver_register(&qcom_icc_bcm_voter_driver);
|
||||
}
|
||||
module_init(qcom_icc_bcm_voter_driver_init);
|
||||
|
||||
MODULE_AUTHOR("David Dai <daidavid1@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Qualcomm BCM Voter interconnect driver");
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_INTERCONNECT_QCOM_BCM_VOTER_H__
|
||||
|
175
drivers/interconnect/qcom/icc-debug.c
Normal file
175
drivers/interconnect/qcom/icc-debug.c
Normal file
@@ -0,0 +1,175 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <trace/events/power.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
static LIST_HEAD(icc_providers);
|
||||
static DEFINE_MUTEX(debug_lock);
|
||||
static struct dentry *dentry_suspend;
|
||||
static bool debug_suspend;
|
||||
|
||||
struct qcom_icc_debug_provider {
|
||||
struct list_head list;
|
||||
struct icc_provider *provider;
|
||||
};
|
||||
|
||||
static int icc_print_enabled(void)
|
||||
{
|
||||
struct qcom_icc_debug_provider *dp;
|
||||
struct icc_provider *provider;
|
||||
struct icc_node *n;
|
||||
struct icc_req *r;
|
||||
u32 avg_bw, peak_bw;
|
||||
|
||||
pr_info(" node tag avg peak\n");
|
||||
pr_info("--------------------------------------------------------------------\n");
|
||||
|
||||
list_for_each_entry(dp, &icc_providers, list) {
|
||||
provider = dp->provider;
|
||||
|
||||
list_for_each_entry(n, &provider->nodes, node_list) {
|
||||
if (!n->avg_bw && !n->peak_bw)
|
||||
continue;
|
||||
|
||||
pr_info("%-42s %12u %12u\n",
|
||||
n->name, n->avg_bw, n->peak_bw);
|
||||
|
||||
hlist_for_each_entry(r, &n->req_list, req_node) {
|
||||
if (!r->dev)
|
||||
continue;
|
||||
|
||||
if (r->enabled) {
|
||||
avg_bw = r->avg_bw;
|
||||
peak_bw = r->peak_bw;
|
||||
} else {
|
||||
avg_bw = 0;
|
||||
peak_bw = 0;
|
||||
}
|
||||
|
||||
if (avg_bw || peak_bw)
|
||||
pr_info(" %-27s %12u %12u %12u\n",
|
||||
dev_name(r->dev), r->tag, avg_bw, peak_bw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icc_debug_suspend_get(void *data, u64 *val)
|
||||
{
|
||||
*val = debug_suspend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void icc_debug_suspend_trace_probe(void *unused, const char *action,
|
||||
int val, bool start)
|
||||
{
|
||||
if (start && val > 0 && !strcmp("machine_suspend", action)) {
|
||||
pr_info("Enabled interconnect votes:\n");
|
||||
icc_print_enabled();
|
||||
}
|
||||
}
|
||||
|
||||
static int icc_debug_suspend_set(void *data, u64 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
val = !!val;
|
||||
if (val == debug_suspend)
|
||||
return 0;
|
||||
|
||||
if (val)
|
||||
ret = register_trace_suspend_resume(icc_debug_suspend_trace_probe, NULL);
|
||||
else
|
||||
ret = unregister_trace_suspend_resume(icc_debug_suspend_trace_probe, NULL);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to %sregister suspend trace callback, ret=%d\n",
|
||||
__func__, val ? "" : "un", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
debug_suspend = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(icc_debug_suspend_fops, icc_debug_suspend_get,
|
||||
icc_debug_suspend_set, "%llu\n");
|
||||
|
||||
int qcom_icc_debug_register(struct icc_provider *provider)
|
||||
{
|
||||
struct qcom_icc_debug_provider *dp;
|
||||
|
||||
dp = kzalloc(sizeof(*dp), GFP_KERNEL);
|
||||
if (!dp)
|
||||
return -ENOMEM;
|
||||
|
||||
dp->provider = provider;
|
||||
|
||||
mutex_lock(&debug_lock);
|
||||
list_add_tail(&dp->list, &icc_providers);
|
||||
mutex_unlock(&debug_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_debug_register);
|
||||
|
||||
int qcom_icc_debug_unregister(struct icc_provider *provider)
|
||||
{
|
||||
struct qcom_icc_debug_provider *dp, *temp;
|
||||
|
||||
mutex_lock(&debug_lock);
|
||||
|
||||
list_for_each_entry_safe(dp, temp, &icc_providers, list) {
|
||||
if (dp->provider == provider) {
|
||||
list_del(&dp->list);
|
||||
kfree(dp);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&debug_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_debug_unregister);
|
||||
|
||||
static int __init qcom_icc_debug_init(void)
|
||||
{
|
||||
static struct dentry *dir;
|
||||
int ret;
|
||||
|
||||
dir = debugfs_lookup("interconnect", NULL);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
ret = PTR_ERR(dir);
|
||||
pr_err("%s: unable to find root interconnect debugfs directory, ret=%d\n",
|
||||
__func__, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dentry_suspend = debugfs_create_file_unsafe("debug_suspend",
|
||||
0644, dir, NULL,
|
||||
&icc_debug_suspend_fops);
|
||||
return 0;
|
||||
}
|
||||
module_init(qcom_icc_debug_init);
|
||||
|
||||
static void __exit qcom_icc_debug_exit(void)
|
||||
{
|
||||
debugfs_remove(dentry_suspend);
|
||||
if (debug_suspend)
|
||||
unregister_trace_suspend_resume(icc_debug_suspend_trace_probe, NULL);
|
||||
}
|
||||
module_exit(qcom_icc_debug_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QCOM ICC debug library");
|
||||
MODULE_LICENSE("GPL");
|
12
drivers/interconnect/qcom/icc-debug.h
Normal file
12
drivers/interconnect/qcom/icc-debug.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef __QCOM_ICC_DEBUG_H__
|
||||
#define __QCOM_ICC_DEBUG_H__
|
||||
|
||||
#include <linux/interconnect-provider.h>
|
||||
|
||||
int qcom_icc_debug_register(struct icc_provider *provider);
|
||||
int qcom_icc_debug_unregister(struct icc_provider *provider);
|
||||
|
||||
#endif
|
@@ -1,266 +1,68 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2020 Linaro Ltd
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <asm/div64.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
|
||||
#include "icc-common.h"
|
||||
#include "icc-rpm.h"
|
||||
#include "qnoc-qos-rpm.h"
|
||||
|
||||
/* QNOC QoS */
|
||||
#define QNOC_QOS_MCTL_LOWn_ADDR(n) (0x8 + (n * 0x1000))
|
||||
#define QNOC_QOS_MCTL_DFLT_PRIO_MASK 0x70
|
||||
#define QNOC_QOS_MCTL_DFLT_PRIO_SHIFT 4
|
||||
#define QNOC_QOS_MCTL_URGFWD_EN_MASK 0x8
|
||||
#define QNOC_QOS_MCTL_URGFWD_EN_SHIFT 3
|
||||
|
||||
/* BIMC QoS */
|
||||
#define M_BKE_REG_BASE(n) (0x300 + (0x4000 * n))
|
||||
#define M_BKE_EN_ADDR(n) (M_BKE_REG_BASE(n))
|
||||
#define M_BKE_HEALTH_CFG_ADDR(i, n) (M_BKE_REG_BASE(n) + 0x40 + (0x4 * i))
|
||||
|
||||
#define M_BKE_HEALTH_CFG_LIMITCMDS_MASK 0x80000000
|
||||
#define M_BKE_HEALTH_CFG_AREQPRIO_MASK 0x300
|
||||
#define M_BKE_HEALTH_CFG_PRIOLVL_MASK 0x3
|
||||
#define M_BKE_HEALTH_CFG_AREQPRIO_SHIFT 0x8
|
||||
#define M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT 0x1f
|
||||
|
||||
#define M_BKE_EN_EN_BMASK 0x1
|
||||
|
||||
/* NoC QoS */
|
||||
#define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000))
|
||||
#define NOC_QOS_PRIORITY_P1_MASK 0xc
|
||||
#define NOC_QOS_PRIORITY_P0_MASK 0x3
|
||||
#define NOC_QOS_PRIORITY_P1_SHIFT 0x2
|
||||
|
||||
#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000))
|
||||
#define NOC_QOS_MODEn_MASK 0x3
|
||||
|
||||
#define NOC_QOS_MODE_FIXED_VAL 0x0
|
||||
#define NOC_QOS_MODE_BYPASS_VAL 0x2
|
||||
|
||||
#define ICC_BUS_CLK_MIN_RATE 19200ULL /* kHz */
|
||||
|
||||
static int qcom_icc_set_qnoc_qos(struct icc_node *src)
|
||||
static int qcom_icc_rpm_smd_send_msg(int ctx, int rsc_type, int rpm_id, u64 val)
|
||||
{
|
||||
struct icc_provider *provider = src->provider;
|
||||
struct qcom_icc_provider *qp = to_qcom_provider(provider);
|
||||
struct qcom_icc_node *qn = src->data;
|
||||
struct qcom_icc_qos *qos = &qn->qos;
|
||||
int rc;
|
||||
int ret;
|
||||
struct msm_rpm_kvp rpm_kvp;
|
||||
|
||||
rc = regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
|
||||
QNOC_QOS_MCTL_DFLT_PRIO_MASK,
|
||||
qos->areq_prio << QNOC_QOS_MCTL_DFLT_PRIO_SHIFT);
|
||||
if (rc)
|
||||
return rc;
|
||||
rpm_kvp.length = sizeof(uint64_t);
|
||||
rpm_kvp.key = RPM_MASTER_FIELD_BW;
|
||||
rpm_kvp.data = (uint8_t *)&val;
|
||||
|
||||
return regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
|
||||
QNOC_QOS_MCTL_URGFWD_EN_MASK,
|
||||
!!qos->urg_fwd_en << QNOC_QOS_MCTL_URGFWD_EN_SHIFT);
|
||||
}
|
||||
ret = msm_rpm_send_message(ctx, rsc_type, rpm_id, &rpm_kvp, 1);
|
||||
|
||||
static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp,
|
||||
struct qcom_icc_qos *qos,
|
||||
int regnum)
|
||||
{
|
||||
u32 val;
|
||||
u32 mask;
|
||||
|
||||
val = qos->prio_level;
|
||||
mask = M_BKE_HEALTH_CFG_PRIOLVL_MASK;
|
||||
|
||||
val |= qos->areq_prio << M_BKE_HEALTH_CFG_AREQPRIO_SHIFT;
|
||||
mask |= M_BKE_HEALTH_CFG_AREQPRIO_MASK;
|
||||
|
||||
/* LIMITCMDS is not present on M_BKE_HEALTH_3 */
|
||||
if (regnum != 3) {
|
||||
val |= qos->limit_commands << M_BKE_HEALTH_CFG_LIMITCMDS_SHIFT;
|
||||
mask |= M_BKE_HEALTH_CFG_LIMITCMDS_MASK;
|
||||
}
|
||||
|
||||
return regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + M_BKE_HEALTH_CFG_ADDR(regnum, qos->qos_port),
|
||||
mask, val);
|
||||
}
|
||||
|
||||
static int qcom_icc_set_bimc_qos(struct icc_node *src)
|
||||
{
|
||||
struct qcom_icc_provider *qp;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_provider *provider;
|
||||
u32 mode = NOC_QOS_MODE_BYPASS;
|
||||
u32 val = 0;
|
||||
int i, rc = 0;
|
||||
|
||||
qn = src->data;
|
||||
provider = src->provider;
|
||||
qp = to_qcom_provider(provider);
|
||||
|
||||
if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID)
|
||||
mode = qn->qos.qos_mode;
|
||||
|
||||
/* QoS Priority: The QoS Health parameters are getting considered
|
||||
* only if we are NOT in Bypass Mode.
|
||||
*/
|
||||
if (mode != NOC_QOS_MODE_BYPASS) {
|
||||
for (i = 3; i >= 0; i--) {
|
||||
rc = qcom_icc_bimc_set_qos_health(qp,
|
||||
&qn->qos, i);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Set BKE_EN to 1 when Fixed, Regulator or Limiter Mode */
|
||||
val = 1;
|
||||
}
|
||||
|
||||
return regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + M_BKE_EN_ADDR(qn->qos.qos_port),
|
||||
M_BKE_EN_EN_BMASK, val);
|
||||
}
|
||||
|
||||
static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp,
|
||||
struct qcom_icc_qos *qos)
|
||||
{
|
||||
u32 val;
|
||||
int rc;
|
||||
|
||||
/* Must be updated one at a time, P1 first, P0 last */
|
||||
val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT;
|
||||
rc = regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
|
||||
NOC_QOS_PRIORITY_P1_MASK, val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + NOC_QOS_PRIORITYn_ADDR(qos->qos_port),
|
||||
NOC_QOS_PRIORITY_P0_MASK, qos->prio_level);
|
||||
}
|
||||
|
||||
static int qcom_icc_set_noc_qos(struct icc_node *src)
|
||||
{
|
||||
struct qcom_icc_provider *qp;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_provider *provider;
|
||||
u32 mode = NOC_QOS_MODE_BYPASS_VAL;
|
||||
int rc = 0;
|
||||
|
||||
qn = src->data;
|
||||
provider = src->provider;
|
||||
qp = to_qcom_provider(provider);
|
||||
|
||||
if (qn->qos.qos_port < 0) {
|
||||
dev_dbg(src->provider->dev,
|
||||
"NoC QoS: Skipping %s: vote aggregated on parent.\n",
|
||||
qn->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (qn->qos.qos_mode == NOC_QOS_MODE_FIXED) {
|
||||
dev_dbg(src->provider->dev, "NoC QoS: %s: Set Fixed mode\n", qn->name);
|
||||
mode = NOC_QOS_MODE_FIXED_VAL;
|
||||
rc = qcom_icc_noc_set_qos_priority(qp, &qn->qos);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (qn->qos.qos_mode == NOC_QOS_MODE_BYPASS) {
|
||||
dev_dbg(src->provider->dev, "NoC QoS: %s: Set Bypass mode\n", qn->name);
|
||||
mode = NOC_QOS_MODE_BYPASS_VAL;
|
||||
} else {
|
||||
/* How did we get here? */
|
||||
}
|
||||
|
||||
return regmap_update_bits(qp->regmap,
|
||||
qp->qos_offset + NOC_QOS_MODEn_ADDR(qn->qos.qos_port),
|
||||
NOC_QOS_MODEn_MASK, mode);
|
||||
}
|
||||
|
||||
static int qcom_icc_qos_set(struct icc_node *node)
|
||||
{
|
||||
struct qcom_icc_provider *qp = to_qcom_provider(node->provider);
|
||||
struct qcom_icc_node *qn = node->data;
|
||||
|
||||
dev_dbg(node->provider->dev, "Setting QoS for %s\n", qn->name);
|
||||
|
||||
switch (qp->type) {
|
||||
case QCOM_ICC_BIMC:
|
||||
return qcom_icc_set_bimc_qos(node);
|
||||
case QCOM_ICC_QNOC:
|
||||
return qcom_icc_set_qnoc_qos(node);
|
||||
default:
|
||||
return qcom_icc_set_noc_qos(node);
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 *bw)
|
||||
{
|
||||
int ret, rpm_ctx = 0;
|
||||
u64 bw_bps;
|
||||
|
||||
if (qn->qos.ap_owned)
|
||||
return 0;
|
||||
|
||||
for (rpm_ctx = 0; rpm_ctx < QCOM_SMD_RPM_STATE_NUM; rpm_ctx++) {
|
||||
bw_bps = icc_units_to_bps(bw[rpm_ctx]);
|
||||
|
||||
if (qn->mas_rpm_id != -1) {
|
||||
ret = qcom_icc_rpm_smd_send(rpm_ctx,
|
||||
RPM_BUS_MASTER_REQ,
|
||||
qn->mas_rpm_id,
|
||||
bw_bps);
|
||||
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(rpm_ctx,
|
||||
RPM_BUS_SLAVE_REQ,
|
||||
qn->slv_rpm_id,
|
||||
bw_bps);
|
||||
if (ret) {
|
||||
pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
|
||||
qn->slv_rpm_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests
|
||||
* qcom_icc_get_bw_stub - initializes the bw values to zero
|
||||
* @node: icc node to operate on
|
||||
* @avg_bw: initial bw to sum aggregate
|
||||
* @peak_bw: initial bw to max aggregate
|
||||
*/
|
||||
int qcom_icc_get_bw_stub(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_get_bw_stub);
|
||||
|
||||
/**
|
||||
* qcom_icc_rpm_pre_aggregate - cleans up stale values from prior icc_set
|
||||
* @node: icc node to operate on
|
||||
*/
|
||||
static void qcom_icc_pre_bw_aggregate(struct icc_node *node)
|
||||
void qcom_icc_rpm_pre_aggregate(struct icc_node *node)
|
||||
{
|
||||
struct qcom_icc_node *qn;
|
||||
size_t i;
|
||||
struct qcom_icc_node *qn;
|
||||
|
||||
qn = node->data;
|
||||
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
|
||||
|
||||
for (i = 0; i < RPM_NUM_CXT; i++) {
|
||||
qn->sum_avg[i] = 0;
|
||||
qn->max_peak[i] = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_rpm_pre_aggregate);
|
||||
|
||||
/**
|
||||
* qcom_icc_bw_aggregate - aggregate bw for buckets indicated by tag
|
||||
* qcom_icc_rpm_aggregate - aggregate bw for buckets indicated by tag
|
||||
* @node: node to aggregate
|
||||
* @tag: tag to indicate which buckets to aggregate
|
||||
* @avg_bw: new bw to sum aggregate
|
||||
@@ -268,18 +70,20 @@ static void qcom_icc_pre_bw_aggregate(struct icc_node *node)
|
||||
* @agg_avg: existing aggregate avg bw val
|
||||
* @agg_peak: existing aggregate peak bw val
|
||||
*/
|
||||
static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
int qcom_icc_rpm_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
size_t i;
|
||||
struct qcom_icc_node *qn;
|
||||
|
||||
qn = node->data;
|
||||
|
||||
if (!tag)
|
||||
tag = RPM_ALWAYS_TAG;
|
||||
if (tag && !(tag & QCOM_ICC_TAG_SLEEP))
|
||||
tag = BIT(RPM_ACTIVE_CXT);
|
||||
else
|
||||
tag = BIT(RPM_SLEEP_CXT) | BIT(RPM_ACTIVE_CXT);
|
||||
|
||||
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
|
||||
for (i = 0; i < RPM_NUM_CXT; i++) {
|
||||
if (tag & BIT(i)) {
|
||||
qn->sum_avg[i] += avg_bw;
|
||||
qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
|
||||
@@ -288,301 +92,144 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max_t(u32, *agg_peak, peak_bw);
|
||||
|
||||
qn->dirty = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_rpm_aggregate);
|
||||
|
||||
/**
|
||||
* qcom_icc_bus_aggregate - calculate bus clock rates by traversing all nodes
|
||||
* @provider: generic interconnect provider
|
||||
* @agg_clk_rate: array containing the aggregated clock rates in kHz
|
||||
* qcom_icc_rpm_set - set the constraints based on path
|
||||
* @src: source node for the path to set constraints on
|
||||
* @dst: destination node for the path to set constraints on
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
static void qcom_icc_bus_aggregate(struct icc_provider *provider, u64 *agg_clk_rate)
|
||||
int qcom_icc_rpm_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
u64 agg_avg_rate, agg_rate;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_node *node;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Iterate nodes on the provider, aggregate bandwidth requests for
|
||||
* every bucket and convert them into bus clock rates.
|
||||
*/
|
||||
list_for_each_entry(node, &provider->nodes, node_list) {
|
||||
qn = node->data;
|
||||
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
|
||||
if (qn->channels)
|
||||
agg_avg_rate = div_u64(qn->sum_avg[i], qn->channels);
|
||||
else
|
||||
agg_avg_rate = qn->sum_avg[i];
|
||||
|
||||
agg_rate = max_t(u64, agg_avg_rate, qn->max_peak[i]);
|
||||
do_div(agg_rate, qn->buswidth);
|
||||
|
||||
agg_clk_rate[i] = max_t(u64, agg_clk_rate[i], agg_rate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct qcom_icc_node *src_qn = NULL, *dst_qn = NULL;
|
||||
u64 agg_clk_rate[QCOM_SMD_RPM_STATE_NUM] = { 0 };
|
||||
struct icc_provider *provider;
|
||||
struct qcom_icc_provider *qp;
|
||||
u64 active_rate, sleep_rate;
|
||||
int ret;
|
||||
struct qcom_icc_node *qn;
|
||||
struct icc_node *n, *node;
|
||||
struct icc_provider *provider;
|
||||
int ret, i;
|
||||
int rpm_ctx;
|
||||
u64 clk_rate, sum_avg, max_peak;
|
||||
u64 bus_clk_rate[RPM_NUM_CXT] = {0, 0};
|
||||
|
||||
src_qn = src->data;
|
||||
if (dst)
|
||||
dst_qn = dst->data;
|
||||
provider = src->provider;
|
||||
qp = to_qcom_provider(provider);
|
||||
if (!src)
|
||||
node = dst;
|
||||
else
|
||||
node = src;
|
||||
|
||||
qcom_icc_bus_aggregate(provider, agg_clk_rate);
|
||||
active_rate = agg_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE];
|
||||
sleep_rate = agg_clk_rate[QCOM_SMD_RPM_SLEEP_STATE];
|
||||
qp = to_qcom_provider(node->provider);
|
||||
qn = node->data;
|
||||
|
||||
ret = qcom_icc_rpm_set(src_qn, src_qn->sum_avg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (dst_qn) {
|
||||
ret = qcom_icc_rpm_set(dst_qn, dst_qn->sum_avg);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Some providers don't have a bus clock to scale */
|
||||
if (!qp->bus_clk_desc && !qp->bus_clk)
|
||||
if (!qn->dirty)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Downstream checks whether the requested rate is zero, but it makes little sense
|
||||
* to vote for a value that's below the lower threshold, so let's not do so.
|
||||
*/
|
||||
if (qp->keep_alive)
|
||||
active_rate = max(ICC_BUS_CLK_MIN_RATE, active_rate);
|
||||
provider = node->provider;
|
||||
|
||||
/* Some providers have a non-RPM-owned bus clock - convert kHz->Hz for the CCF */
|
||||
if (qp->bus_clk) {
|
||||
active_rate = max_t(u64, active_rate, sleep_rate);
|
||||
/* ARM32 caps clk_set_rate arg to u32.. Nothing we can do about that! */
|
||||
active_rate = min_t(u64, 1000ULL * active_rate, ULONG_MAX);
|
||||
return clk_set_rate(qp->bus_clk, active_rate);
|
||||
}
|
||||
list_for_each_entry(n, &provider->nodes, node_list) {
|
||||
qn = n->data;
|
||||
for (i = 0; i < RPM_NUM_CXT; i++) {
|
||||
sum_avg = icc_units_to_bps(qn->sum_avg[i]);
|
||||
|
||||
/* RPM only accepts <=INT_MAX rates */
|
||||
active_rate = min_t(u64, active_rate, INT_MAX);
|
||||
sleep_rate = min_t(u64, sleep_rate, INT_MAX);
|
||||
sum_avg *= qp->util_factor;
|
||||
do_div(sum_avg, DEFAULT_UTIL_FACTOR);
|
||||
|
||||
if (active_rate != qp->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE]) {
|
||||
ret = qcom_icc_rpm_set_bus_rate(qp->bus_clk_desc, QCOM_SMD_RPM_ACTIVE_STATE,
|
||||
active_rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
do_div(sum_avg, qn->channels);
|
||||
max_peak = icc_units_to_bps(qn->max_peak[i]);
|
||||
|
||||
/* Cache the rate after we've successfully commited it to RPM */
|
||||
qp->bus_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE] = active_rate;
|
||||
}
|
||||
clk_rate = max(sum_avg, max_peak);
|
||||
do_div(clk_rate, qn->buswidth);
|
||||
|
||||
if (sleep_rate != qp->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE]) {
|
||||
ret = qcom_icc_rpm_set_bus_rate(qp->bus_clk_desc, QCOM_SMD_RPM_SLEEP_STATE,
|
||||
sleep_rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
bus_clk_rate[i] = max(bus_clk_rate[i], clk_rate);
|
||||
|
||||
/* Cache the rate after we've successfully commited it to RPM */
|
||||
qp->bus_clk_rate[QCOM_SMD_RPM_SLEEP_STATE] = sleep_rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qnoc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct qcom_icc_desc *desc;
|
||||
struct icc_onecell_data *data;
|
||||
struct icc_provider *provider;
|
||||
struct qcom_icc_node * const *qnodes;
|
||||
struct qcom_icc_provider *qp;
|
||||
struct icc_node *node;
|
||||
size_t num_nodes, i;
|
||||
const char * const *cds = NULL;
|
||||
int cd_num;
|
||||
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;
|
||||
|
||||
if (desc->num_intf_clocks) {
|
||||
cds = desc->intf_clocks;
|
||||
cd_num = desc->num_intf_clocks;
|
||||
} else {
|
||||
/* 0 intf clocks is perfectly fine */
|
||||
cd_num = 0;
|
||||
}
|
||||
|
||||
qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
|
||||
if (!qp)
|
||||
return -ENOMEM;
|
||||
|
||||
qp->intf_clks = devm_kcalloc(dev, cd_num, sizeof(*qp->intf_clks), GFP_KERNEL);
|
||||
if (!qp->intf_clks)
|
||||
return -ENOMEM;
|
||||
|
||||
if (desc->bus_clk_desc) {
|
||||
qp->bus_clk_desc = devm_kzalloc(dev, sizeof(*qp->bus_clk_desc),
|
||||
GFP_KERNEL);
|
||||
if (!qp->bus_clk_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
qp->bus_clk_desc = desc->bus_clk_desc;
|
||||
} else {
|
||||
/* Some older SoCs may have a single non-RPM-owned bus clock. */
|
||||
qp->bus_clk = devm_clk_get_optional(dev, "bus");
|
||||
if (IS_ERR(qp->bus_clk))
|
||||
return PTR_ERR(qp->bus_clk);
|
||||
}
|
||||
|
||||
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
qp->num_intf_clks = cd_num;
|
||||
for (i = 0; i < cd_num; i++)
|
||||
qp->intf_clks[i].id = cds[i];
|
||||
|
||||
qp->keep_alive = desc->keep_alive;
|
||||
qp->type = desc->type;
|
||||
qp->qos_offset = desc->qos_offset;
|
||||
|
||||
if (desc->regmap_cfg) {
|
||||
struct resource *res;
|
||||
void __iomem *mmio;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
/* Try parent's regmap */
|
||||
qp->regmap = dev_get_regmap(dev->parent, NULL);
|
||||
if (qp->regmap)
|
||||
goto regmap_done;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mmio = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mmio))
|
||||
return PTR_ERR(mmio);
|
||||
|
||||
qp->regmap = devm_regmap_init_mmio(dev, mmio, desc->regmap_cfg);
|
||||
if (IS_ERR(qp->regmap)) {
|
||||
dev_err(dev, "Cannot regmap interconnect bus resource\n");
|
||||
return PTR_ERR(qp->regmap);
|
||||
if (bus_clk_rate[i] > RPM_CLK_MAX_LEVEL)
|
||||
bus_clk_rate[i] = RPM_CLK_MAX_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
regmap_done:
|
||||
ret = clk_prepare_enable(qp->bus_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (i = 0; i < RPM_NUM_CXT; i++) {
|
||||
if (qp->bus_clk_cur_rate[i] != bus_clk_rate[i]) {
|
||||
if (qp->keepalive && i == RPM_ACTIVE_CXT) {
|
||||
if (qp->init)
|
||||
ret = clk_set_rate(qp->bus_clks[i].clk,
|
||||
RPM_CLK_MAX_LEVEL);
|
||||
else if (bus_clk_rate[i] == 0)
|
||||
ret = clk_set_rate(qp->bus_clks[i].clk,
|
||||
RPM_CLK_MIN_LEVEL);
|
||||
else
|
||||
ret = clk_set_rate(qp->bus_clks[i].clk,
|
||||
bus_clk_rate[i]);
|
||||
} else {
|
||||
ret = clk_set_rate(qp->bus_clks[i].clk,
|
||||
bus_clk_rate[i]);
|
||||
}
|
||||
|
||||
ret = devm_clk_bulk_get(dev, qp->num_intf_clks, qp->intf_clks);
|
||||
if (ret)
|
||||
goto err_disable_unprepare_clk;
|
||||
|
||||
provider = &qp->provider;
|
||||
provider->dev = dev;
|
||||
provider->set = qcom_icc_set;
|
||||
provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
|
||||
provider->aggregate = qcom_icc_bw_aggregate;
|
||||
provider->xlate_extended = qcom_icc_xlate_extended;
|
||||
provider->data = data;
|
||||
|
||||
icc_provider_init(provider);
|
||||
|
||||
/* If this fails, bus accesses will crash the platform! */
|
||||
ret = clk_bulk_prepare_enable(qp->num_intf_clks, qp->intf_clks);
|
||||
if (ret)
|
||||
goto err_disable_unprepare_clk;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
size_t j;
|
||||
|
||||
node = icc_node_create(qnodes[i]->id);
|
||||
if (IS_ERR(node)) {
|
||||
clk_bulk_disable_unprepare(qp->num_intf_clks,
|
||||
qp->intf_clks);
|
||||
ret = PTR_ERR(node);
|
||||
goto err_remove_nodes;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
/* Set QoS registers (we only need to do it once, generally) */
|
||||
if (qnodes[i]->qos.ap_owned &&
|
||||
qnodes[i]->qos.qos_mode != NOC_QOS_MODE_INVALID) {
|
||||
ret = qcom_icc_qos_set(node);
|
||||
if (ret) {
|
||||
clk_bulk_disable_unprepare(qp->num_intf_clks,
|
||||
qp->intf_clks);
|
||||
goto err_remove_nodes;
|
||||
pr_err("%s clk_set_rate error: %d\n",
|
||||
qp->bus_clks[i].id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
qp->bus_clk_cur_rate[i] = bus_clk_rate[i];
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(n, &provider->nodes, node_list) {
|
||||
qn = n->data;
|
||||
if (!qn->dirty)
|
||||
continue;
|
||||
|
||||
qn->dirty = false;
|
||||
if ((qn->mas_rpm_id == -1) && (qn->slv_rpm_id == -1))
|
||||
continue;
|
||||
|
||||
/* send bandwidth request message to the RPM processor */
|
||||
for (i = 0; i < RPM_NUM_CXT; i++) {
|
||||
if (qn->last_sum_avg[i] != qn->sum_avg[i]) {
|
||||
rpm_ctx = (i == RPM_SLEEP_CXT) ?
|
||||
RPM_SLEEP_SET : RPM_ACTIVE_SET;
|
||||
|
||||
sum_avg = icc_units_to_bps(qn->sum_avg[i]);
|
||||
|
||||
if (qn->mas_rpm_id != -1) {
|
||||
ret = qcom_icc_rpm_smd_send_msg(
|
||||
rpm_ctx,
|
||||
RPM_BUS_MASTER_REQ,
|
||||
qn->mas_rpm_id,
|
||||
sum_avg);
|
||||
|
||||
if (ret) {
|
||||
pr_err("qcom_icc_rpm_smd_send_msg mas %d error %d\n",
|
||||
qn->mas_rpm_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (qn->slv_rpm_id != -1) {
|
||||
ret = qcom_icc_rpm_smd_send_msg(
|
||||
rpm_ctx,
|
||||
RPM_BUS_SLAVE_REQ,
|
||||
qn->slv_rpm_id,
|
||||
sum_avg);
|
||||
|
||||
if (ret) {
|
||||
pr_err("qcom_icc_rpm_smd_send_msg slv %d error %d\n",
|
||||
qn->slv_rpm_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
qn->last_sum_avg[i] = qn->sum_avg[i];
|
||||
}
|
||||
}
|
||||
|
||||
data->nodes[i] = node;
|
||||
}
|
||||
data->num_nodes = num_nodes;
|
||||
|
||||
clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
|
||||
|
||||
ret = icc_provider_register(provider);
|
||||
if (ret)
|
||||
goto err_remove_nodes;
|
||||
|
||||
platform_set_drvdata(pdev, qp);
|
||||
|
||||
/* Populate child NoC devices if any */
|
||||
if (of_get_child_count(dev->of_node) > 0) {
|
||||
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||
if (ret)
|
||||
goto err_deregister_provider;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_deregister_provider:
|
||||
icc_provider_deregister(provider);
|
||||
err_remove_nodes:
|
||||
icc_nodes_remove(provider);
|
||||
err_disable_unprepare_clk:
|
||||
clk_disable_unprepare(qp->bus_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qnoc_probe);
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_rpm_set);
|
||||
|
||||
int qnoc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
|
||||
|
||||
icc_provider_deregister(&qp->provider);
|
||||
icc_nodes_remove(&qp->provider);
|
||||
clk_disable_unprepare(qp->bus_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qnoc_remove);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -1,88 +1,69 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020 Linaro Ltd
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H
|
||||
#define __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H
|
||||
|
||||
#include <linux/soc/qcom/smd-rpm.h>
|
||||
|
||||
#include <dt-bindings/interconnect/qcom,rpm-icc.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <soc/qcom/rpm-smd.h>
|
||||
|
||||
#define RPM_BUS_MASTER_REQ 0x73616d62
|
||||
#define RPM_BUS_SLAVE_REQ 0x766c7362
|
||||
|
||||
#define QCOM_MAX_LINKS 128
|
||||
|
||||
#define RPM_SLEEP_SET MSM_RPM_CTX_SLEEP_SET
|
||||
#define RPM_ACTIVE_SET MSM_RPM_CTX_ACTIVE_SET
|
||||
#define RPM_CLK_MAX_LEVEL INT_MAX
|
||||
#define RPM_CLK_MIN_LEVEL 19200000
|
||||
|
||||
#define DEFAULT_UTIL_FACTOR 100
|
||||
|
||||
#define to_qcom_provider(_provider) \
|
||||
container_of(_provider, struct qcom_icc_provider, provider)
|
||||
|
||||
enum qcom_icc_type {
|
||||
QCOM_ICC_NOC,
|
||||
QCOM_ICC_BIMC,
|
||||
QCOM_ICC_QNOC,
|
||||
enum qcom_icc_rpm_mas_field_type {
|
||||
RPM_MASTER_FIELD_BW = 0x00007762,
|
||||
RPM_MASTER_FIELD_BW_T0 = 0x30747762,
|
||||
RPM_MASTER_FIELD_BW_T1 = 0x31747762,
|
||||
RPM_MASTER_FIELD_BW_T2 = 0x32747762,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rpm_clk_resource - RPM bus clock resource
|
||||
* @resource_type: RPM resource type of the clock resource
|
||||
* @clock_id: index of the clock resource of a specific resource type
|
||||
* @branch: whether the resource represents a branch clock
|
||||
*/
|
||||
struct rpm_clk_resource {
|
||||
u32 resource_type;
|
||||
u32 clock_id;
|
||||
bool branch;
|
||||
enum qcom_icc_rpm_context {
|
||||
RPM_SLEEP_CXT,
|
||||
RPM_ACTIVE_CXT,
|
||||
RPM_NUM_CXT
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_icc_provider - Qualcomm specific interconnect provider
|
||||
* @provider: generic interconnect provider
|
||||
* @num_intf_clks: the total number of intf_clks clk_bulk_data entries
|
||||
* @type: the ICC provider type
|
||||
* @regmap: regmap for QoS registers read/write access
|
||||
* @qos_offset: offset to QoS registers
|
||||
* @bus_clk_rate: bus clock rate in Hz
|
||||
* @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks
|
||||
* @bus_clk: a pointer to a HLOS-owned bus clock
|
||||
* @intf_clks: a clk_bulk_data array of interface clocks
|
||||
* @keep_alive: whether to always keep a minimum vote on the bus clocks
|
||||
* @is_on: whether the bus is powered on
|
||||
* @dev: reference to the NoC device
|
||||
* @qos_clks: the clk_bulk_data table of QoS clocks
|
||||
* @num_qos_clks: the total number of clk_bulk_data entries
|
||||
* @bus_clks: the clk_bulk_data table of bus clocks
|
||||
* @num_clks: the total number of clk_bulk_data entries
|
||||
* @bus_clk_cur_rate: current frequency of bus clock
|
||||
* @keepalive: flag used to indicate whether a keepalive is required
|
||||
* @init: flag to determine when init has completed.
|
||||
*/
|
||||
struct qcom_icc_provider {
|
||||
struct icc_provider provider;
|
||||
int num_intf_clks;
|
||||
enum qcom_icc_type type;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
unsigned int qos_offset;
|
||||
u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
|
||||
const struct rpm_clk_resource *bus_clk_desc;
|
||||
struct clk *bus_clk;
|
||||
struct clk_bulk_data *intf_clks;
|
||||
bool keep_alive;
|
||||
bool is_on;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_icc_qos - Qualcomm specific interconnect QoS parameters
|
||||
* @areq_prio: node requests priority
|
||||
* @prio_level: priority level for bus communication
|
||||
* @limit_commands: activate/deactivate limiter mode during runtime
|
||||
* @ap_owned: indicates if the node is owned by the AP or by the RPM
|
||||
* @qos_mode: default qos mode for this node
|
||||
* @qos_port: qos port number for finding qos registers of this node
|
||||
* @urg_fwd_en: enable urgent forwarding
|
||||
*/
|
||||
struct qcom_icc_qos {
|
||||
u32 areq_prio;
|
||||
u32 prio_level;
|
||||
bool limit_commands;
|
||||
bool ap_owned;
|
||||
int qos_mode;
|
||||
int qos_port;
|
||||
bool urg_fwd_en;
|
||||
struct list_head probe_list;
|
||||
struct clk_bulk_data *qos_clks;
|
||||
int num_qos_clks;
|
||||
struct clk_bulk_data *bus_clks;
|
||||
int num_clks;
|
||||
u32 util_factor;
|
||||
u64 bus_clk_cur_rate[RPM_NUM_CXT];
|
||||
bool keepalive;
|
||||
bool init;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -91,65 +72,43 @@ struct qcom_icc_qos {
|
||||
* @id: a unique node identifier
|
||||
* @links: an array of nodes where we can go next while traversing
|
||||
* @num_links: the total number of @links
|
||||
* @channels: number of channels at this node (e.g. DDR channels)
|
||||
* @channels: num of channels at this node
|
||||
* @buswidth: width of the interconnect between a node and the bus (bytes)
|
||||
* @last_sum_avg: aggregated average bandwidth from previous aggregation
|
||||
* @sum_avg: current sum aggregate value of all avg bw requests
|
||||
* @max_peak: current max aggregate value of all peak bw requests
|
||||
* @mas_rpm_id: RPM id for devices that are bus masters
|
||||
* @slv_rpm_id: RPM id for devices that are bus slaves
|
||||
* @qos: NoC QoS setting parameters
|
||||
* @rate: current bus clock rate in Hz
|
||||
* @dirty: flag used to indicate whether the node needs to be committed
|
||||
*/
|
||||
struct qcom_icc_node {
|
||||
unsigned char *name;
|
||||
u16 id;
|
||||
const u16 *links;
|
||||
u16 links[QCOM_MAX_LINKS];
|
||||
u16 num_links;
|
||||
u16 channels;
|
||||
u16 buswidth;
|
||||
u64 sum_avg[QCOM_SMD_RPM_STATE_NUM];
|
||||
u64 max_peak[QCOM_SMD_RPM_STATE_NUM];
|
||||
u64 last_sum_avg[RPM_NUM_CXT];
|
||||
u64 sum_avg[RPM_NUM_CXT];
|
||||
u64 max_peak[RPM_NUM_CXT];
|
||||
int mas_rpm_id;
|
||||
int slv_rpm_id;
|
||||
struct qcom_icc_qos qos;
|
||||
u64 rate;
|
||||
struct regmap *regmap;
|
||||
struct qcom_icc_qosbox *qosbox;
|
||||
const struct qcom_icc_noc_ops *noc_ops;
|
||||
bool dirty;
|
||||
};
|
||||
|
||||
struct qcom_icc_desc {
|
||||
struct qcom_icc_node * const *nodes;
|
||||
struct qcom_icc_node **nodes;
|
||||
size_t num_nodes;
|
||||
const struct rpm_clk_resource *bus_clk_desc;
|
||||
const char * const *intf_clocks;
|
||||
size_t num_intf_clocks;
|
||||
bool keep_alive;
|
||||
enum qcom_icc_type type;
|
||||
const struct regmap_config *regmap_cfg;
|
||||
unsigned int qos_offset;
|
||||
};
|
||||
|
||||
/* Valid for all bus types */
|
||||
enum qos_mode {
|
||||
NOC_QOS_MODE_INVALID = 0,
|
||||
NOC_QOS_MODE_FIXED,
|
||||
NOC_QOS_MODE_BYPASS,
|
||||
};
|
||||
|
||||
extern const struct rpm_clk_resource aggre1_clk;
|
||||
extern const struct rpm_clk_resource aggre2_clk;
|
||||
extern const struct rpm_clk_resource bimc_clk;
|
||||
extern const struct rpm_clk_resource bus_0_clk;
|
||||
extern const struct rpm_clk_resource bus_1_clk;
|
||||
extern const struct rpm_clk_resource bus_2_clk;
|
||||
extern const struct rpm_clk_resource mmaxi_0_clk;
|
||||
extern const struct rpm_clk_resource mmaxi_1_clk;
|
||||
extern const struct rpm_clk_resource qup_clk;
|
||||
|
||||
extern const struct rpm_clk_resource aggre1_branch_clk;
|
||||
extern const struct rpm_clk_resource aggre2_branch_clk;
|
||||
|
||||
int qnoc_probe(struct platform_device *pdev);
|
||||
int qnoc_remove(struct platform_device *pdev);
|
||||
|
||||
bool qcom_icc_rpm_smd_available(void);
|
||||
int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val);
|
||||
int qcom_icc_rpm_set_bus_rate(const struct rpm_clk_resource *clk, int ctx, u32 rate);
|
||||
|
||||
int qcom_icc_rpm_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
|
||||
int qcom_icc_rpm_set(struct icc_node *src, struct icc_node *dst);
|
||||
void qcom_icc_rpm_pre_aggregate(struct icc_node *node);
|
||||
int qcom_icc_get_bw_stub(struct icc_node *node, u32 *avg, u32 *peak);
|
||||
#endif
|
||||
|
@@ -1,18 +1,23 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/slab.h>
|
||||
#include <soc/qcom/socinfo.h>
|
||||
|
||||
#include "bcm-voter.h"
|
||||
#include "icc-common.h"
|
||||
#include "icc-debug.h"
|
||||
#include "icc-rpmh.h"
|
||||
#include "qnoc-qos.h"
|
||||
|
||||
/**
|
||||
* qcom_icc_pre_aggregate - cleans up stale values from prior icc_set
|
||||
@@ -30,13 +35,19 @@ void qcom_icc_pre_aggregate(struct icc_node *node)
|
||||
for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
|
||||
qn->sum_avg[i] = 0;
|
||||
qn->max_peak[i] = 0;
|
||||
qn->perf_mode[i] = false;
|
||||
}
|
||||
|
||||
for (i = 0; i < qn->num_bcms; i++)
|
||||
qcom_icc_bcm_voter_add(qp->voter, qn->bcms[i]);
|
||||
qcom_icc_bcm_voter_add(qp->voters[qn->bcms[i]->voter_idx],
|
||||
qn->bcms[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_pre_aggregate);
|
||||
|
||||
static void qcom_icc_pre_aggregate_stub(struct icc_node *node)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_icc_aggregate - aggregate bw for buckets indicated by tag
|
||||
* @node: node to aggregate
|
||||
@@ -61,6 +72,8 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
if (tag & BIT(i)) {
|
||||
qn->sum_avg[i] += avg_bw;
|
||||
qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
|
||||
if (tag & QCOM_ICC_TAG_PERF_MODE && (avg_bw || peak_bw))
|
||||
qn->perf_mode[i] = true;
|
||||
}
|
||||
|
||||
if (node->init_avg || node->init_peak) {
|
||||
@@ -76,6 +89,13 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_aggregate);
|
||||
|
||||
int qcom_icc_aggregate_stub(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_aggregate_stub);
|
||||
|
||||
/**
|
||||
* qcom_icc_set - set the constraints based on path
|
||||
* @src: source node for the path to set constraints on
|
||||
@@ -87,6 +107,9 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct qcom_icc_provider *qp;
|
||||
struct icc_node *node;
|
||||
struct qcom_icc_node *qn;
|
||||
u64 clk_rate;
|
||||
int i, ret;
|
||||
|
||||
if (!src)
|
||||
node = dst;
|
||||
@@ -94,13 +117,78 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
node = src;
|
||||
|
||||
qp = to_qcom_provider(node->provider);
|
||||
qn = node->data;
|
||||
|
||||
qcom_icc_bcm_voter_commit(qp->voter);
|
||||
if (qn->bw_scale_numerator && qn->bw_scale_denominator) {
|
||||
node->avg_bw *= qn->bw_scale_numerator;
|
||||
do_div(node->avg_bw, qn->bw_scale_denominator);
|
||||
|
||||
node->peak_bw *= qn->bw_scale_numerator;
|
||||
do_div(node->peak_bw, qn->bw_scale_denominator);
|
||||
}
|
||||
|
||||
if (qn->clk) {
|
||||
/*
|
||||
* Multiply by 1000 to convert the unit of bandwidth from KBps
|
||||
* to Bps, then divide by the bandwidth to get the clk rate in Hz.
|
||||
*/
|
||||
clk_rate = (u64)max(node->avg_bw, node->peak_bw) * 1000 / qn->buswidth;
|
||||
clk_rate = clk_rate > U32_MAX ? U32_MAX : clk_rate;
|
||||
|
||||
if (clk_rate > 0) {
|
||||
ret = clk_set_rate(qn->clk, clk_rate);
|
||||
if (ret)
|
||||
dev_warn(qp->dev, "Failed to set %s rate to %llu for %s\n",
|
||||
qn->clk_name, clk_rate, qn->name);
|
||||
|
||||
if (qn->toggle_clk && !qn->clk_enabled) {
|
||||
ret = clk_prepare_enable(qn->clk);
|
||||
if (ret) {
|
||||
dev_err(qp->dev, "Failed to enable %s for %s\n",
|
||||
qn->clk_name, qn->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
qn->clk_enabled = true;
|
||||
}
|
||||
} else if (qn->toggle_clk && qn->clk_enabled) {
|
||||
clk_disable_unprepare(qn->clk);
|
||||
qn->clk_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < qp->num_voters; i++)
|
||||
qcom_icc_bcm_voter_commit(qp->voters[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_set);
|
||||
|
||||
int qcom_icc_set_stub(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_set_stub);
|
||||
|
||||
int qcom_icc_get_bw_stub(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_get_bw_stub);
|
||||
|
||||
int qcom_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
struct qcom_icc_node *qn = node->data;
|
||||
|
||||
*peak = qn->init_peak;
|
||||
*avg = qn->init_avg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_icc_bcm_init - populates bcm aux data and connect qnodes
|
||||
* @bcm: bcm to be initialized
|
||||
@@ -108,15 +196,17 @@ EXPORT_SYMBOL_GPL(qcom_icc_set);
|
||||
*
|
||||
* Return: 0 on success, or an error code otherwise
|
||||
*/
|
||||
int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
|
||||
int qcom_icc_bcm_init(struct qcom_icc_provider *qp, struct qcom_icc_bcm *bcm,
|
||||
struct device *dev)
|
||||
{
|
||||
struct qcom_icc_node *qn;
|
||||
const struct bcm_db *data;
|
||||
struct bcm_voter *voter;
|
||||
size_t data_count;
|
||||
int i;
|
||||
|
||||
/* BCM is already initialised*/
|
||||
if (bcm->addr)
|
||||
if (bcm->disabled || bcm->addr)
|
||||
return 0;
|
||||
|
||||
bcm->addr = cmd_db_read_addr(bcm->name);
|
||||
@@ -138,8 +228,8 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcm->aux_data.unit = le32_to_cpu(data->unit);
|
||||
bcm->aux_data.width = le16_to_cpu(data->width);
|
||||
bcm->aux_data.unit = max_t(u32, 1, le32_to_cpu(data->unit));
|
||||
bcm->aux_data.width = max_t(u16, 1, le16_to_cpu(data->width));
|
||||
bcm->aux_data.vcd = data->vcd;
|
||||
bcm->aux_data.reserved = data->reserved;
|
||||
INIT_LIST_HEAD(&bcm->list);
|
||||
@@ -155,10 +245,188 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
|
||||
qn->num_bcms++;
|
||||
}
|
||||
|
||||
if (bcm->keepalive) {
|
||||
/*
|
||||
* Default vote for keepalive BCMs, use the first node as proxy node
|
||||
*/
|
||||
qn = bcm->nodes[0];
|
||||
qn->init_avg = INT_MAX;
|
||||
qn->init_peak = INT_MAX;
|
||||
|
||||
voter = qp->voters[bcm->voter_idx];
|
||||
qcom_icc_bcm_voter_add(voter, bcm);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_bcm_init);
|
||||
|
||||
static bool bcm_needs_qos_proxy(struct qcom_icc_bcm *bcm)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (bcm->qos_proxy)
|
||||
return true;
|
||||
|
||||
if (bcm->voter_idx == 0)
|
||||
for (i = 0; i < bcm->num_nodes; i++)
|
||||
if (bcm->nodes[i]->qosbox)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int enable_qos_deps(struct qcom_icc_provider *qp)
|
||||
{
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct bcm_voter *voter;
|
||||
bool keepalive;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < qp->num_bcms; i++) {
|
||||
bcm = qp->bcms[i];
|
||||
if (bcm_needs_qos_proxy(bcm)) {
|
||||
keepalive = bcm->keepalive;
|
||||
bcm->keepalive = true;
|
||||
|
||||
voter = qp->voters[bcm->voter_idx];
|
||||
qcom_icc_bcm_voter_add(voter, bcm);
|
||||
ret = qcom_icc_bcm_voter_commit(voter);
|
||||
|
||||
bcm->keepalive = keepalive;
|
||||
|
||||
if (ret) {
|
||||
dev_err(qp->dev, "failed to vote BW to %s for QoS\n",
|
||||
bcm->name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare_enable(qp->num_clks, qp->clks);
|
||||
if (ret) {
|
||||
dev_err(qp->dev, "failed to enable clocks for QoS\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void disable_qos_deps(struct qcom_icc_provider *qp)
|
||||
{
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct bcm_voter *voter;
|
||||
int i;
|
||||
|
||||
clk_bulk_disable_unprepare(qp->num_clks, qp->clks);
|
||||
|
||||
for (i = 0; i < qp->num_bcms; i++) {
|
||||
bcm = qp->bcms[i];
|
||||
if (bcm_needs_qos_proxy(bcm)) {
|
||||
voter = qp->voters[bcm->voter_idx];
|
||||
qcom_icc_bcm_voter_add(voter, bcm);
|
||||
qcom_icc_bcm_voter_commit(voter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int qcom_icc_rpmh_configure_qos(struct qcom_icc_provider *qp)
|
||||
{
|
||||
struct qcom_icc_node *qnode;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
ret = enable_qos_deps(qp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < qp->num_nodes; i++) {
|
||||
qnode = qp->nodes[i];
|
||||
if (!qnode)
|
||||
continue;
|
||||
|
||||
if (qnode->qosbox)
|
||||
qnode->noc_ops->set_qos(qnode);
|
||||
}
|
||||
|
||||
disable_qos_deps(qp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_rpmh_configure_qos);
|
||||
|
||||
static struct regmap *qcom_icc_rpmh_map(struct platform_device *pdev,
|
||||
const struct qcom_icc_desc *desc)
|
||||
{
|
||||
void __iomem *base;
|
||||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (IS_ERR(base))
|
||||
return ERR_CAST(base);
|
||||
|
||||
return devm_regmap_init_mmio(dev, base, desc->config);
|
||||
}
|
||||
|
||||
static bool is_voter_disabled(struct device *dev, char *voter)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
int idx = 0;
|
||||
|
||||
if (!voter || !np)
|
||||
return true;
|
||||
|
||||
idx = of_property_match_string(np, "qcom,disabled-voters", voter);
|
||||
if (idx >= 0)
|
||||
return true;
|
||||
|
||||
if ((strnstr(voter, "disp", strlen(voter)) && socinfo_get_part_info(PART_DISPLAY)) ||
|
||||
(strnstr(voter, "cam", strlen(voter)) && socinfo_get_part_info(PART_CAMERA)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int qcom_icc_init_disabled_parts(struct qcom_icc_provider *qp)
|
||||
{
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct qcom_icc_node * const *qnodes, *qn;
|
||||
const struct qcom_icc_desc *desc;
|
||||
int voter_idx, i, j;
|
||||
char *voter_name;
|
||||
|
||||
desc = of_device_get_match_data(qp->dev);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < qp->num_bcms; i++) {
|
||||
bcm = qp->bcms[i];
|
||||
voter_idx = bcm->voter_idx;
|
||||
voter_name = desc->voters[voter_idx];
|
||||
|
||||
/* Disable BCMs incase of NO display or No Camera */
|
||||
if (is_voter_disabled(qp->dev, voter_name)) {
|
||||
bcm->disabled = true;
|
||||
qnodes = qp->nodes;
|
||||
|
||||
for (j = 0; j < qp->num_nodes; j++) {
|
||||
qn = qnodes[j];
|
||||
if (!qn)
|
||||
continue;
|
||||
|
||||
if (strnstr(qn->name, voter_name, strlen(qn->name)))
|
||||
qn->disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qcom_icc_rpmh_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct qcom_icc_desc *desc;
|
||||
@@ -187,38 +455,90 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
data->num_nodes = num_nodes;
|
||||
|
||||
qp->stub = of_property_read_bool(pdev->dev.of_node, "qcom,stub");
|
||||
qp->skip_qos = of_property_read_bool(pdev->dev.of_node, "qcom,skip-qos");
|
||||
|
||||
provider = &qp->provider;
|
||||
provider->dev = dev;
|
||||
|
||||
provider->set = qcom_icc_set;
|
||||
provider->pre_aggregate = qcom_icc_pre_aggregate;
|
||||
provider->aggregate = qcom_icc_aggregate;
|
||||
provider->xlate_extended = qcom_icc_xlate_extended;
|
||||
provider->data = data;
|
||||
provider->get_bw = qcom_icc_get_bw;
|
||||
|
||||
if (qp->stub) {
|
||||
provider->set = qcom_icc_set_stub;
|
||||
provider->pre_aggregate = qcom_icc_pre_aggregate_stub;
|
||||
provider->aggregate = qcom_icc_aggregate_stub;
|
||||
}
|
||||
|
||||
icc_provider_init(provider);
|
||||
|
||||
qp->dev = dev;
|
||||
qp->bcms = desc->bcms;
|
||||
qp->num_bcms = desc->num_bcms;
|
||||
qp->nodes = desc->nodes;
|
||||
qp->num_nodes = desc->num_nodes;
|
||||
|
||||
qp->voter = of_bcm_voter_get(qp->dev, NULL);
|
||||
if (IS_ERR(qp->voter))
|
||||
return PTR_ERR(qp->voter);
|
||||
if (!qp->stub) {
|
||||
qp->num_bcms = desc->num_bcms;
|
||||
qp->num_voters = desc->num_voters;
|
||||
|
||||
qp->voters = devm_kcalloc(&pdev->dev, qp->num_voters,
|
||||
sizeof(*qp->voters), GFP_KERNEL);
|
||||
|
||||
if (!qp->voters)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = qcom_icc_init_disabled_parts(qp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < qp->num_voters; i++) {
|
||||
if (desc->voters[i] && !is_voter_disabled(qp->dev, desc->voters[i])) {
|
||||
qp->voters[i] = of_bcm_voter_get(qp->dev, desc->voters[i]);
|
||||
if (IS_ERR(qp->voters[i]))
|
||||
return PTR_ERR(qp->voters[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qp->regmap = qcom_icc_rpmh_map(pdev, desc);
|
||||
if (IS_ERR(qp->regmap))
|
||||
return PTR_ERR(qp->regmap);
|
||||
|
||||
qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks);
|
||||
if (qp->num_clks < 0)
|
||||
return qp->num_clks;
|
||||
|
||||
for (i = 0; i < qp->num_bcms; i++)
|
||||
qcom_icc_bcm_init(qp->bcms[i], dev);
|
||||
qcom_icc_bcm_init(qp, qp->bcms[i], dev);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
qn = qnodes[i];
|
||||
if (!qn)
|
||||
if (!qn || qn->disabled)
|
||||
continue;
|
||||
|
||||
qn->regmap = dev_get_regmap(qp->dev, NULL);
|
||||
|
||||
node = icc_node_create(qn->id);
|
||||
if (IS_ERR(node)) {
|
||||
ret = PTR_ERR(node);
|
||||
goto err_remove_nodes;
|
||||
}
|
||||
|
||||
if (qn->clk_name) {
|
||||
qn->clk = devm_clk_get(qp->dev, qn->clk_name);
|
||||
if (IS_ERR(qn->clk)) {
|
||||
ret = PTR_ERR(qn->clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(qp->dev, "failed to get %s, err:(%d)\n",
|
||||
qn->clk_name, ret);
|
||||
goto err_remove_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
node->name = qn->name;
|
||||
node->data = qn;
|
||||
icc_node_add(node, provider);
|
||||
@@ -229,6 +549,12 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
|
||||
data->nodes[i] = node;
|
||||
}
|
||||
|
||||
if (!qp->skip_qos) {
|
||||
ret = qcom_icc_rpmh_configure_qos(qp);
|
||||
if (ret)
|
||||
goto err_remove_nodes;
|
||||
}
|
||||
|
||||
ret = icc_provider_register(provider);
|
||||
if (ret)
|
||||
goto err_remove_nodes;
|
||||
@@ -242,6 +568,8 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
|
||||
goto err_deregister_provider;
|
||||
}
|
||||
|
||||
qcom_icc_debug_register(provider);
|
||||
|
||||
return 0;
|
||||
|
||||
err_deregister_provider:
|
||||
@@ -257,6 +585,9 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
|
||||
|
||||
qcom_icc_debug_unregister(&qp->provider);
|
||||
clk_bulk_put_all(qp->num_clks, qp->clks);
|
||||
|
||||
icc_provider_deregister(&qp->provider);
|
||||
icc_nodes_remove(&qp->provider);
|
||||
|
||||
|
@@ -1,12 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__
|
||||
#define __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__
|
||||
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <soc/qcom/crm.h>
|
||||
|
||||
#define to_qcom_provider(_provider) \
|
||||
container_of(_provider, struct qcom_icc_provider, provider)
|
||||
@@ -24,7 +29,16 @@ struct qcom_icc_provider {
|
||||
struct device *dev;
|
||||
struct qcom_icc_bcm * const *bcms;
|
||||
size_t num_bcms;
|
||||
struct bcm_voter *voter;
|
||||
struct qcom_icc_node * const *nodes;
|
||||
size_t num_nodes;
|
||||
struct list_head probe_list;
|
||||
struct regmap *regmap;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
struct bcm_voter **voters;
|
||||
size_t num_voters;
|
||||
bool stub;
|
||||
bool skip_qos;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -46,6 +60,14 @@ struct bcm_db {
|
||||
#define MAX_BCM_PER_NODE 3
|
||||
#define MAX_VCD 10
|
||||
|
||||
struct qcom_icc_crm_voter {
|
||||
const char *name;
|
||||
const struct device *dev;
|
||||
enum crm_drv_type client_type;
|
||||
u32 client_idx;
|
||||
u32 pwr_states;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_icc_node - Qualcomm specific interconnect nodes
|
||||
* @name: the node name used in debugfs
|
||||
@@ -56,8 +78,16 @@ struct bcm_db {
|
||||
* @buswidth: width of the interconnect between a node and the bus
|
||||
* @sum_avg: current sum aggregate value of all avg bw requests
|
||||
* @max_peak: current max aggregate value of all peak bw requests
|
||||
* @perf_mode: current OR aggregate value of all QCOM_ICC_TAG_PERF_MODE votes
|
||||
* @bcms: list of bcms associated with this logical node
|
||||
* @num_bcms: num of @bcms
|
||||
* @clk: the local clock at this node
|
||||
* @clk_name: the local clock name at this node
|
||||
* @toggle_clk: flag used to indicate whether local clock can be enabled/disabled
|
||||
* @clk_enabled: flag used to indicate whether local clock have been enabled
|
||||
* @bw_scale_numerator: the numerator of the bandwidth scale factor
|
||||
* @bw_scale_denominator: the denominator of the bandwidth scale factor
|
||||
* @disabled : flag used to indicate state of icc node
|
||||
*/
|
||||
struct qcom_icc_node {
|
||||
const char *name;
|
||||
@@ -68,22 +98,51 @@ struct qcom_icc_node {
|
||||
u16 buswidth;
|
||||
u64 sum_avg[QCOM_ICC_NUM_BUCKETS];
|
||||
u64 max_peak[QCOM_ICC_NUM_BUCKETS];
|
||||
bool perf_mode[QCOM_ICC_NUM_BUCKETS];
|
||||
u32 init_avg;
|
||||
u32 init_peak;
|
||||
struct qcom_icc_bcm *bcms[MAX_BCM_PER_NODE];
|
||||
size_t num_bcms;
|
||||
struct regmap *regmap;
|
||||
struct qcom_icc_qosbox *qosbox;
|
||||
const struct qcom_icc_noc_ops *noc_ops;
|
||||
struct clk *clk;
|
||||
const char *clk_name;
|
||||
bool toggle_clk;
|
||||
bool clk_enabled;
|
||||
u16 bw_scale_numerator;
|
||||
u16 bw_scale_denominator;
|
||||
bool disabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum qcom_icc_bcm_type - The type of aggregation used by a BCM
|
||||
*
|
||||
* @QCOM_ICC_BCM_TYPE_BW: Aggregates SUM of vote_x and MAX of vote_y
|
||||
* @QCOM_ICC_BCM_TYPE_MASK: Aggregates bitwise OR of vote_y
|
||||
*/
|
||||
enum qcom_icc_bcm_type {
|
||||
QCOM_ICC_BCM_TYPE_BW,
|
||||
QCOM_ICC_BCM_TYPE_MASK,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_icc_bcm - Qualcomm specific hardware accelerator nodes
|
||||
* known as Bus Clock Manager (BCM)
|
||||
* @name: the bcm node name used to fetch BCM data from command db
|
||||
* @type: latency or bandwidth bcm
|
||||
* @type: aggregation strategy used by this BCM
|
||||
* @addr: address offsets used when voting to RPMH
|
||||
* @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm
|
||||
* @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm
|
||||
* @vote_scale: scaling factor for vote_x and vote_y
|
||||
* @enable_mask: optional mask to send as vote instead of vote_x/vote_y
|
||||
* @perf_mode_mask: mask to OR with enable_mask when QCOM_ICC_TAG_PERF_MODE is set
|
||||
* @dirty: flag used to indicate whether the bcm needs to be committed
|
||||
* @keepalive: flag used to indicate whether a keepalive is required
|
||||
* @keepalive_early: keepalive only prior to sync-state
|
||||
* @qos_proxy: flag used to indicate whether a proxy vote needed as part of
|
||||
* qos configuration
|
||||
* @disabled: flag used to indicate state of bcm node
|
||||
* @aux_data: auxiliary data used when calculating threshold values and
|
||||
* communicating with RPMh
|
||||
* @list: used to link to other bcms when compiling lists for commit
|
||||
@@ -93,17 +152,23 @@ struct qcom_icc_node {
|
||||
*/
|
||||
struct qcom_icc_bcm {
|
||||
const char *name;
|
||||
u32 type;
|
||||
enum qcom_icc_bcm_type type;
|
||||
u32 addr;
|
||||
u64 vote_x[QCOM_ICC_NUM_BUCKETS];
|
||||
u64 vote_y[QCOM_ICC_NUM_BUCKETS];
|
||||
u64 vote_scale;
|
||||
u32 enable_mask;
|
||||
u32 perf_mode_mask;
|
||||
bool dirty;
|
||||
bool keepalive;
|
||||
bool keepalive_early;
|
||||
bool qos_proxy;
|
||||
bool disabled;
|
||||
struct bcm_db aux_data;
|
||||
struct list_head list;
|
||||
struct list_head ws_list;
|
||||
int voter_idx;
|
||||
u8 crm_node;
|
||||
size_t num_nodes;
|
||||
struct qcom_icc_node *nodes[];
|
||||
};
|
||||
@@ -115,17 +180,24 @@ struct qcom_icc_fabric {
|
||||
|
||||
struct qcom_icc_desc {
|
||||
struct qcom_icc_node * const *nodes;
|
||||
const struct regmap_config *config;
|
||||
size_t num_nodes;
|
||||
struct qcom_icc_bcm * const *bcms;
|
||||
size_t num_bcms;
|
||||
char **voters;
|
||||
size_t num_voters;
|
||||
};
|
||||
|
||||
int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
|
||||
int qcom_icc_aggregate_stub(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
|
||||
int qcom_icc_set(struct icc_node *src, struct icc_node *dst);
|
||||
int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev);
|
||||
int qcom_icc_set_stub(struct icc_node *src, struct icc_node *dst);
|
||||
int qcom_icc_bcm_init(struct qcom_icc_provider *qp, struct qcom_icc_bcm *bcm, struct device *dev);
|
||||
void qcom_icc_pre_aggregate(struct icc_node *node);
|
||||
int qcom_icc_rpmh_probe(struct platform_device *pdev);
|
||||
int qcom_icc_rpmh_remove(struct platform_device *pdev);
|
||||
|
||||
int qcom_icc_get_bw_stub(struct icc_node *node, u32 *avg, u32 *peak);
|
||||
int qcom_icc_rpmh_configure_qos(struct qcom_icc_provider *qp);
|
||||
#endif
|
||||
|
1803
drivers/interconnect/qcom/monaco.c
Normal file
1803
drivers/interconnect/qcom/monaco.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
* Qualcomm MSM8996 Network-on-Chip (NoC) QoS driver
|
||||
*
|
||||
* Copyright (c) 2021 Yassine Oudjana <y.oudjana@protonmail.com>
|
||||
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@@ -2117,12 +2118,6 @@ static int __init qnoc_driver_init(void)
|
||||
}
|
||||
core_initcall(qnoc_driver_init);
|
||||
|
||||
static void __exit qnoc_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qnoc_driver);
|
||||
}
|
||||
module_exit(qnoc_driver_exit);
|
||||
|
||||
MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
|
||||
MODULE_DESCRIPTION("Qualcomm MSM8996 NoC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
2502
drivers/interconnect/qcom/parrot.c
Normal file
2502
drivers/interconnect/qcom/parrot.c
Normal file
File diff suppressed because it is too large
Load Diff
3351
drivers/interconnect/qcom/pineapple.c
Normal file
3351
drivers/interconnect/qcom/pineapple.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1059,11 +1059,5 @@ static int __init qnoc_driver_init(void)
|
||||
}
|
||||
core_initcall(qnoc_driver_init);
|
||||
|
||||
static void __exit qnoc_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qnoc_driver);
|
||||
}
|
||||
module_exit(qnoc_driver_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QDU1000 NoC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
125
drivers/interconnect/qcom/qnoc-qos-rpm.c
Normal file
125
drivers/interconnect/qcom/qnoc-qos-rpm.c
Normal file
@@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "icc-rpm.h"
|
||||
#include "qnoc-qos-rpm.h"
|
||||
|
||||
#define QOSGEN_MAINCTL_LO(p, qp) ((p)->offsets[qp] + \
|
||||
(p)->regs[QOSGEN_OFF_MAINCTL_LO])
|
||||
#define QOS_SLV_URG_MSG_EN_SHFT 3
|
||||
#define QOS_DFLT_PRIO_MASK 0x7
|
||||
#define QOS_DFLT_PRIO_SHFT 4
|
||||
#define QOS_DISABLE_SHIFT 24
|
||||
|
||||
#define QOSGEN_M_BKE_HEALTH(p, qp, n) ((p)->offsets[qp] + ((n) * 4) + \
|
||||
(p)->regs[QOSGEN_OFF_MPORT_BKE_HEALTH])
|
||||
#define QOS_PRIOLVL_MASK 0x7
|
||||
#define QOS_PRIOLVL_SHFT 0x0
|
||||
#define QOS_AREQPRIO_MASK 0x70
|
||||
#define QOS_AREQPRIO_SHFT 0x8
|
||||
|
||||
#define QOSGEN_M_BKE_EN(p, qp) ((p)->offsets[qp] + \
|
||||
(p)->regs[QOSGEN_OFF_MPORT_BKE_EN])
|
||||
|
||||
#define QOS_BKE_EN_MASK 0x1
|
||||
#define QOS_BKE_EN_SHFT 0x0
|
||||
|
||||
#define NUM_BKE_HEALTH_LEVELS 4
|
||||
|
||||
const u8 icc_qnoc_qos_regs[][QOSGEN_OFF_MAX_REGS] = {
|
||||
[ICC_QNOC_QOSGEN_TYPE_RPMH] = {
|
||||
[QOSGEN_OFF_MAINCTL_LO] = 0x8,
|
||||
[QOSGEN_OFF_LIMITBW_LO] = 0x18,
|
||||
[QOSGEN_OFF_SHAPING_LO] = 0x20,
|
||||
[QOSGEN_OFF_SHAPING_HI] = 0x24,
|
||||
[QOSGEN_OFF_REGUL0CTL_LO] = 0x40,
|
||||
[QOSGEN_OFF_REGUL0BW_LO] = 0x48,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(icc_qnoc_qos_regs);
|
||||
|
||||
const u8 icc_bimc_qos_regs[][QOSGEN_OFF_MAX_REGS] = {
|
||||
[ICC_QNOC_QOSGEN_TYPE_RPMH] = {
|
||||
[QOSGEN_OFF_MPORT_BKE_EN] = 0x0,
|
||||
[QOSGEN_OFF_MPORT_BKE_HEALTH] = 0x40,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(icc_bimc_qos_regs);
|
||||
|
||||
/**
|
||||
* qcom_icc_set_qos - initialize static QoS configurations
|
||||
* @node: qcom icc node to operate on
|
||||
*/
|
||||
static void qcom_icc_set_qos(struct qcom_icc_node *node)
|
||||
{
|
||||
struct qcom_icc_qosbox *qos = node->qosbox;
|
||||
int port;
|
||||
|
||||
if (!node->regmap)
|
||||
return;
|
||||
|
||||
if (!qos)
|
||||
return;
|
||||
|
||||
for (port = 0; port < qos->num_ports; port++) {
|
||||
regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port),
|
||||
BIT(QOS_DISABLE_SHIFT),
|
||||
qos->config->prio_fwd_disable << QOS_DISABLE_SHIFT);
|
||||
|
||||
regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port),
|
||||
QOS_DFLT_PRIO_MASK << QOS_DFLT_PRIO_SHFT,
|
||||
qos->config->prio << QOS_DFLT_PRIO_SHFT);
|
||||
|
||||
regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port),
|
||||
BIT(QOS_SLV_URG_MSG_EN_SHFT),
|
||||
qos->config->urg_fwd << QOS_SLV_URG_MSG_EN_SHFT);
|
||||
}
|
||||
}
|
||||
|
||||
const struct qcom_icc_noc_ops qcom_qnoc4_ops = {
|
||||
.set_qos = qcom_icc_set_qos,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(qcom_qnoc4_ops);
|
||||
|
||||
/**
|
||||
* qcom_icc_set_bimc_qos - initialize static QoS configurations
|
||||
* @node: qcom icc node to operate on
|
||||
*/
|
||||
static void qcom_icc_set_bimc_qos(struct qcom_icc_node *node)
|
||||
{
|
||||
struct qcom_icc_qosbox *qos = node->qosbox;
|
||||
int port, i;
|
||||
|
||||
if (!node->regmap)
|
||||
return;
|
||||
|
||||
if (!qos)
|
||||
return;
|
||||
|
||||
for (port = 0; port < qos->num_ports; port++) {
|
||||
for (i = 0; i < NUM_BKE_HEALTH_LEVELS; i++) {
|
||||
regmap_update_bits(node->regmap,
|
||||
QOSGEN_M_BKE_HEALTH(qos, port, i),
|
||||
((qos->config->prio << QOS_PRIOLVL_SHFT) |
|
||||
(qos->config->prio << QOS_AREQPRIO_SHFT)),
|
||||
(QOS_PRIOLVL_MASK | QOS_AREQPRIO_MASK));
|
||||
}
|
||||
|
||||
regmap_update_bits(node->regmap,
|
||||
QOSGEN_M_BKE_EN(qos, port),
|
||||
qos->config->bke_enable << QOS_BKE_EN_SHFT,
|
||||
QOS_BKE_EN_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
const struct qcom_icc_noc_ops qcom_bimc_ops = {
|
||||
.set_qos = qcom_icc_set_bimc_qos,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(qcom_bimc_ops);
|
||||
MODULE_LICENSE("GPL");
|
54
drivers/interconnect/qcom/qnoc-qos-rpm.h
Normal file
54
drivers/interconnect/qcom/qnoc-qos-rpm.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_INTERCONNECT_QCOM_QNOC_QOS_RPM_H__
|
||||
#define __DRIVERS_INTERCONNECT_QCOM_QNOC_QOS_RPM_H__
|
||||
|
||||
#define QOSGEN_OFF_MAX_REGS 6
|
||||
#define ICC_QNOC_QOS_MAX_TYPE 1
|
||||
|
||||
enum {
|
||||
ICC_QNOC_QOSGEN_TYPE_RPMH,
|
||||
};
|
||||
|
||||
enum {
|
||||
QOSGEN_OFF_MAINCTL_LO,
|
||||
QOSGEN_OFF_LIMITBW_LO,
|
||||
QOSGEN_OFF_SHAPING_LO,
|
||||
QOSGEN_OFF_SHAPING_HI,
|
||||
QOSGEN_OFF_REGUL0CTL_LO,
|
||||
QOSGEN_OFF_REGUL0BW_LO,
|
||||
};
|
||||
|
||||
enum {
|
||||
QOSGEN_OFF_MPORT_BKE_HEALTH,
|
||||
QOSGEN_OFF_MPORT_BKE_EN,
|
||||
};
|
||||
|
||||
extern const u8 icc_qnoc_qos_regs[ICC_QNOC_QOS_MAX_TYPE][QOSGEN_OFF_MAX_REGS];
|
||||
extern const u8 icc_bimc_qos_regs[ICC_QNOC_QOS_MAX_TYPE][QOSGEN_OFF_MAX_REGS];
|
||||
|
||||
struct qcom_icc_noc_ops {
|
||||
void (*set_qos)(struct qcom_icc_node *node);
|
||||
};
|
||||
|
||||
struct qos_config {
|
||||
u32 prio;
|
||||
u32 urg_fwd;
|
||||
bool prio_fwd_disable;
|
||||
u32 bke_enable;
|
||||
};
|
||||
|
||||
struct qcom_icc_qosbox {
|
||||
u32 num_ports;
|
||||
const u8 *regs;
|
||||
bool initialized;
|
||||
struct qos_config *config;
|
||||
u32 offsets[];
|
||||
};
|
||||
|
||||
extern const struct qcom_icc_noc_ops qcom_qnoc4_ops;
|
||||
extern const struct qcom_icc_noc_ops qcom_bimc_ops;
|
||||
#endif
|
69
drivers/interconnect/qcom/qnoc-qos.c
Normal file
69
drivers/interconnect/qcom/qnoc-qos.c
Normal file
@@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "icc-rpmh.h"
|
||||
#include "qnoc-qos.h"
|
||||
|
||||
#define QOSGEN_MAINCTL_LO(p, qp) ((p)->offsets[qp] + \
|
||||
(p)->regs[QOSGEN_OFF_MAINCTL_LO])
|
||||
#define QOS_SLV_URG_MSG_EN_SHFT 3
|
||||
# define QOS_DFLT_PRIO_MASK 0x7
|
||||
# define QOS_DFLT_PRIO_SHFT 4
|
||||
#define QOS_DISABLE_SHIFT 24
|
||||
|
||||
|
||||
const u8 icc_qnoc_qos_regs[][QOSGEN_OFF_MAX_REGS] = {
|
||||
[ICC_QNOC_QOSGEN_TYPE_RPMH] = {
|
||||
[QOSGEN_OFF_MAINCTL_LO] = 0x8,
|
||||
[QOSGEN_OFF_LIMITBW_LO] = 0x18,
|
||||
[QOSGEN_OFF_SHAPING_LO] = 0x20,
|
||||
[QOSGEN_OFF_SHAPING_HI] = 0x24,
|
||||
[QOSGEN_OFF_REGUL0CTL_LO] = 0x40,
|
||||
[QOSGEN_OFF_REGUL0BW_LO] = 0x48,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(icc_qnoc_qos_regs);
|
||||
|
||||
/**
|
||||
* qcom_icc_set_qos - initialize static QoS configurations
|
||||
* @node: qcom icc node to operate on
|
||||
*/
|
||||
static void qcom_icc_set_qos(struct qcom_icc_node *node)
|
||||
{
|
||||
struct qcom_icc_qosbox *qos = node->qosbox;
|
||||
int port;
|
||||
|
||||
if (!node->regmap)
|
||||
return;
|
||||
|
||||
if (!qos)
|
||||
return;
|
||||
|
||||
for (port = 0; port < qos->num_ports; port++) {
|
||||
regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port),
|
||||
BIT(QOS_DISABLE_SHIFT),
|
||||
qos->config->prio_fwd_disable << QOS_DISABLE_SHIFT);
|
||||
|
||||
regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port),
|
||||
QOS_DFLT_PRIO_MASK << QOS_DFLT_PRIO_SHFT,
|
||||
qos->config->prio << QOS_DFLT_PRIO_SHFT);
|
||||
|
||||
regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port),
|
||||
BIT(QOS_SLV_URG_MSG_EN_SHFT),
|
||||
qos->config->urg_fwd << QOS_SLV_URG_MSG_EN_SHFT);
|
||||
}
|
||||
}
|
||||
|
||||
const struct qcom_icc_noc_ops qcom_qnoc4_ops = {
|
||||
.set_qos = qcom_icc_set_qos,
|
||||
};
|
||||
EXPORT_SYMBOL(qcom_qnoc4_ops);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
59
drivers/interconnect/qcom/qnoc-qos.h
Normal file
59
drivers/interconnect/qcom/qnoc-qos.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_INTERCONNECT_QCOM_QNOC_QOS_H__
|
||||
#define __DRIVERS_INTERCONNECT_QCOM_QNOC_QOS_H__
|
||||
|
||||
#define QOSGEN_OFF_MAX_REGS 6
|
||||
#define ICC_QNOC_QOS_MAX_TYPE 1
|
||||
|
||||
enum {
|
||||
ICC_QNOC_QOSGEN_TYPE_RPMH,
|
||||
};
|
||||
|
||||
enum {
|
||||
QOSGEN_OFF_MAINCTL_LO,
|
||||
QOSGEN_OFF_LIMITBW_LO,
|
||||
QOSGEN_OFF_SHAPING_LO,
|
||||
QOSGEN_OFF_SHAPING_HI,
|
||||
QOSGEN_OFF_REGUL0CTL_LO,
|
||||
QOSGEN_OFF_REGUL0BW_LO,
|
||||
};
|
||||
|
||||
extern const u8 icc_qnoc_qos_regs[ICC_QNOC_QOS_MAX_TYPE][QOSGEN_OFF_MAX_REGS];
|
||||
|
||||
struct qcom_icc_noc_ops {
|
||||
void (*set_qos)(struct qcom_icc_node *node);
|
||||
};
|
||||
|
||||
struct qos_config {
|
||||
u32 prio;
|
||||
u32 urg_fwd;
|
||||
bool prio_fwd_disable;
|
||||
};
|
||||
|
||||
struct qcom_icc_qosbox {
|
||||
u32 num_ports;
|
||||
const u8 *regs;
|
||||
struct qos_config *config;
|
||||
u32 offsets[];
|
||||
};
|
||||
|
||||
#define DEFINE_QNODE_QOS(_name, _prio, _urg_fwd, _num_ports, ...) \
|
||||
static struct qos_config _name##_qos_cfg = { \
|
||||
.prio = _prio, \
|
||||
.urg_fwd = _urg_fwd, \
|
||||
}; \
|
||||
static struct qcom_icc_qosbox _name##_qos = { \
|
||||
.num_ports = _num_ports, \
|
||||
.config = &_name##_qos_cfg, \
|
||||
.regs = icc_qnoc_qos_regs[ICC_QNOC_QOSGEN_TYPE_RPMH], \
|
||||
.offsets = {__VA_ARGS__}, \
|
||||
} \
|
||||
|
||||
extern const struct qcom_icc_noc_ops qcom_qnoc4_ops;
|
||||
|
||||
#endif
|
2462
drivers/interconnect/qcom/ravelin.c
Normal file
2462
drivers/interconnect/qcom/ravelin.c
Normal file
File diff suppressed because it is too large
Load Diff
486
drivers/interconnect/qcom/rpm-ids.h
Normal file
486
drivers/interconnect/qcom/rpm-ids.h
Normal file
@@ -0,0 +1,486 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_INTERCONNECT_QCOM_RPM_IDS_H__
|
||||
#define __DRIVERS_INTERCONNECT_QCOM_RPM_IDS_H__
|
||||
|
||||
/*
|
||||
* ID's used in RPM messages
|
||||
*/
|
||||
#define ICBID_MASTER_APPSS_PROC 0
|
||||
#define ICBID_MASTER_MSS_PROC 1
|
||||
#define ICBID_MASTER_MNOC_BIMC 2
|
||||
#define ICBID_MASTER_SNOC_BIMC 3
|
||||
#define ICBID_MASTER_SNOC_BIMC_0 ICBID_MASTER_SNOC_BIMC
|
||||
#define ICBID_MASTER_CNOC_MNOC_MMSS_CFG 4
|
||||
#define ICBID_MASTER_CNOC_MNOC_CFG 5
|
||||
#define ICBID_MASTER_GFX3D 6
|
||||
#define ICBID_MASTER_JPEG 7
|
||||
#define ICBID_MASTER_MDP 8
|
||||
#define ICBID_MASTER_MDP0 ICBID_MASTER_MDP
|
||||
#define ICBID_MASTER_MDPS ICBID_MASTER_MDP
|
||||
#define ICBID_MASTER_VIDEO 9
|
||||
#define ICBID_MASTER_VIDEO_P0 ICBID_MASTER_VIDEO
|
||||
#define ICBID_MASTER_VIDEO_P1 10
|
||||
#define ICBID_MASTER_VFE 11
|
||||
#define ICBID_MASTER_VFE0 ICBID_MASTER_VFE
|
||||
#define ICBID_MASTER_CNOC_ONOC_CFG 12
|
||||
#define ICBID_MASTER_JPEG_OCMEM 13
|
||||
#define ICBID_MASTER_MDP_OCMEM 14
|
||||
#define ICBID_MASTER_VIDEO_P0_OCMEM 15
|
||||
#define ICBID_MASTER_VIDEO_P1_OCMEM 16
|
||||
#define ICBID_MASTER_VFE_OCMEM 17
|
||||
#define ICBID_MASTER_LPASS_AHB 18
|
||||
#define ICBID_MASTER_QDSS_BAM 19
|
||||
#define ICBID_MASTER_SNOC_CFG 20
|
||||
#define ICBID_MASTER_BIMC_SNOC 21
|
||||
#define ICBID_MASTER_BIMC_SNOC_0 ICBID_MASTER_BIMC_SNOC
|
||||
#define ICBID_MASTER_CNOC_SNOC 22
|
||||
#define ICBID_MASTER_CRYPTO 23
|
||||
#define ICBID_MASTER_CRYPTO_CORE0 ICBID_MASTER_CRYPTO
|
||||
#define ICBID_MASTER_CRYPTO_CORE1 24
|
||||
#define ICBID_MASTER_LPASS_PROC 25
|
||||
#define ICBID_MASTER_MSS 26
|
||||
#define ICBID_MASTER_MSS_NAV 27
|
||||
#define ICBID_MASTER_OCMEM_DMA 28
|
||||
#define ICBID_MASTER_PNOC_SNOC 29
|
||||
#define ICBID_MASTER_WCSS 30
|
||||
#define ICBID_MASTER_QDSS_ETR 31
|
||||
#define ICBID_MASTER_USB3 32
|
||||
#define ICBID_MASTER_USB3_0 ICBID_MASTER_USB3
|
||||
#define ICBID_MASTER_SDCC_1 33
|
||||
#define ICBID_MASTER_EMMC ICBID_MASTER_SDCC_1
|
||||
#define ICBID_MASTER_SDCC_3 34
|
||||
#define ICBID_MASTER_SDCC_2 35
|
||||
#define ICBID_MASTER_SDCC_4 36
|
||||
#define ICBID_MASTER_TSIF 37
|
||||
#define ICBID_MASTER_BAM_DMA 38
|
||||
#define ICBID_MASTER_BLSP_2 39
|
||||
#define ICBID_MASTER_USB_HSIC 40
|
||||
#define ICBID_MASTER_BLSP_1 41
|
||||
#define ICBID_MASTER_QUP_1 ICBID_MASTER_BLSP_1
|
||||
#define ICBID_MASTER_USB_HS 42
|
||||
#define ICBID_MASTER_USB_HS1 ICBID_MASTER_USB_HS
|
||||
#define ICBID_MASTER_PNOC_CFG 43
|
||||
#define ICBID_MASTER_SNOC_PNOC 44
|
||||
#define ICBID_MASTER_RPM_INST 45
|
||||
#define ICBID_MASTER_RPM_DATA 46
|
||||
#define ICBID_MASTER_RPM_SYS 47
|
||||
#define ICBID_MASTER_DEHR 48
|
||||
#define ICBID_MASTER_QDSS_DAP 49
|
||||
#define ICBID_MASTER_SPDM 50
|
||||
#define ICBID_MASTER_TIC 51
|
||||
#define ICBID_MASTER_SNOC_CNOC 52
|
||||
#define ICBID_MASTER_GFX3D_OCMEM 53
|
||||
#define ICBID_MASTER_GFX3D_GMEM ICBID_MASTER_GFX3D_OCMEM
|
||||
#define ICBID_MASTER_OVIRT_SNOC 54
|
||||
#define ICBID_MASTER_SNOC_OVIRT 55
|
||||
#define ICBID_MASTER_SNOC_GVIRT ICBID_MASTER_SNOC_OVIRT
|
||||
#define ICBID_MASTER_ONOC_OVIRT 56
|
||||
#define ICBID_MASTER_USB_HS2 57
|
||||
#define ICBID_MASTER_QPIC 58
|
||||
#define ICBID_MASTER_IPA 59
|
||||
#define ICBID_MASTER_DSI 60
|
||||
#define ICBID_MASTER_MDP1 61
|
||||
#define ICBID_MASTER_MDPE ICBID_MASTER_MDP1
|
||||
#define ICBID_MASTER_VPU_PROC 62
|
||||
#define ICBID_MASTER_VPU 63
|
||||
#define ICBID_MASTER_VPU0 ICBID_MASTER_VPU
|
||||
#define ICBID_MASTER_CRYPTO_CORE2 64
|
||||
#define ICBID_MASTER_PCIE_0 65
|
||||
#define ICBID_MASTER_PCIE_1 66
|
||||
#define ICBID_MASTER_SATA 67
|
||||
#define ICBID_MASTER_UFS 68
|
||||
#define ICBID_MASTER_USB3_1 69
|
||||
#define ICBID_MASTER_VIDEO_OCMEM 70
|
||||
#define ICBID_MASTER_VPU1 71
|
||||
#define ICBID_MASTER_VCAP 72
|
||||
#define ICBID_MASTER_EMAC 73
|
||||
#define ICBID_MASTER_BCAST 74
|
||||
#define ICBID_MASTER_MMSS_PROC 75
|
||||
#define ICBID_MASTER_SNOC_BIMC_1 76
|
||||
#define ICBID_MASTER_SNOC_PCNOC 77
|
||||
#define ICBID_MASTER_AUDIO 78
|
||||
#define ICBID_MASTER_MM_INT_0 79
|
||||
#define ICBID_MASTER_MM_INT_1 80
|
||||
#define ICBID_MASTER_MM_INT_2 81
|
||||
#define ICBID_MASTER_MM_INT_BIMC 82
|
||||
#define ICBID_MASTER_MSS_INT 83
|
||||
#define ICBID_MASTER_PCNOC_CFG 84
|
||||
#define ICBID_MASTER_PCNOC_INT_0 85
|
||||
#define ICBID_MASTER_PCNOC_INT_1 86
|
||||
#define ICBID_MASTER_PCNOC_M_0 87
|
||||
#define ICBID_MASTER_PCNOC_M_1 88
|
||||
#define ICBID_MASTER_PCNOC_S_0 89
|
||||
#define ICBID_MASTER_PCNOC_S_1 90
|
||||
#define ICBID_MASTER_PCNOC_S_2 91
|
||||
#define ICBID_MASTER_PCNOC_S_3 92
|
||||
#define ICBID_MASTER_PCNOC_S_4 93
|
||||
#define ICBID_MASTER_PCNOC_S_6 94
|
||||
#define ICBID_MASTER_PCNOC_S_7 95
|
||||
#define ICBID_MASTER_PCNOC_S_8 96
|
||||
#define ICBID_MASTER_PCNOC_S_9 97
|
||||
#define ICBID_MASTER_QDSS_INT 98
|
||||
#define ICBID_MASTER_SNOC_INT_0 99
|
||||
#define ICBID_MASTER_SNOC_INT_1 100
|
||||
#define ICBID_MASTER_SNOC_INT_BIMC 101
|
||||
#define ICBID_MASTER_TCU_0 102
|
||||
#define ICBID_MASTER_TCU_1 103
|
||||
#define ICBID_MASTER_BIMC_INT_0 104
|
||||
#define ICBID_MASTER_BIMC_INT_1 105
|
||||
#define ICBID_MASTER_CAMERA 106
|
||||
#define ICBID_MASTER_RICA 107
|
||||
#define ICBID_MASTER_SNOC_BIMC_2 108
|
||||
#define ICBID_MASTER_BIMC_SNOC_1 109
|
||||
#define ICBID_MASTER_A0NOC_SNOC 110
|
||||
#define ICBID_MASTER_ANOC_SNOC ICBID_MASTER_A0NOC_SNOC
|
||||
#define ICBID_MASTER_A1NOC_SNOC 111
|
||||
#define ICBID_MASTER_A2NOC_SNOC 112
|
||||
#define ICBID_MASTER_PIMEM 113
|
||||
#define ICBID_MASTER_SNOC_VMEM 114
|
||||
#define ICBID_MASTER_CPP 115
|
||||
#define ICBID_MASTER_CNOC_A1NOC 116
|
||||
#define ICBID_MASTER_PNOC_A1NOC 117
|
||||
#define ICBID_MASTER_HMSS 118
|
||||
#define ICBID_MASTER_PCIE_2 119
|
||||
#define ICBID_MASTER_ROTATOR 120
|
||||
#define ICBID_MASTER_VENUS_VMEM 121
|
||||
#define ICBID_MASTER_DCC 122
|
||||
#define ICBID_MASTER_MCDMA 123
|
||||
#define ICBID_MASTER_PCNOC_INT_2 124
|
||||
#define ICBID_MASTER_PCNOC_INT_3 125
|
||||
#define ICBID_MASTER_PCNOC_INT_4 126
|
||||
#define ICBID_MASTER_PCNOC_INT_5 127
|
||||
#define ICBID_MASTER_PCNOC_INT_6 128
|
||||
#define ICBID_MASTER_PCNOC_S_5 129
|
||||
#define ICBID_MASTER_SENSORS_AHB 130
|
||||
#define ICBID_MASTER_SENSORS_PROC 131
|
||||
#define ICBID_MASTER_QSPI 132
|
||||
#define ICBID_MASTER_VFE1 133
|
||||
#define ICBID_MASTER_SNOC_INT_2 134
|
||||
#define ICBID_MASTER_SMMNOC_BIMC 135
|
||||
#define ICBID_MASTER_CRVIRT_A1NOC 136
|
||||
#define ICBID_MASTER_XM_USB_HS1 137
|
||||
#define ICBID_MASTER_XI_USB_HS1 138
|
||||
#define ICBID_MASTER_PCNOC_BIMC_1 139
|
||||
#define ICBID_MASTER_BIMC_PCNOC 140
|
||||
#define ICBID_MASTER_XI_HSIC 141
|
||||
#define ICBID_MASTER_SGMII 142
|
||||
#define ICBID_MASTER_SPMI_FETCHER 143
|
||||
#define ICBID_MASTER_GNOC_BIMC 144
|
||||
#define ICBID_MASTER_CRVIRT_A2NOC 145
|
||||
#define ICBID_MASTER_CNOC_A2NOC 146
|
||||
#define ICBID_MASTER_WLAN 147
|
||||
#define ICBID_MASTER_MSS_CE 148
|
||||
#define ICBID_MASTER_CDSP_PROC 149
|
||||
#define ICBID_MASTER_GNOC_SNOC 150
|
||||
#define ICBID_MASTER_MODEM_WRAPPER 151
|
||||
#define ICBID_MASTER_SDIO 152
|
||||
#define ICBID_MASTER_BIMC_SNOC_PCIE 153
|
||||
#define ICBID_MASTER_WLAN_PROC 154
|
||||
#define ICBID_MASTER_CRVIRT_PCNOC 155
|
||||
#define ICBID_MASTER_WLAN_INT 156
|
||||
#define ICBID_MASTER_PCNOC_S_10 157
|
||||
#define ICBID_MASTER_PCNOC_S_11 158
|
||||
#define ICBID_MASTER_LPASS_LPAIF 159
|
||||
#define ICBID_MASTER_LPASS_LEC 160
|
||||
#define ICBID_MASTER_LPASS_ANOC_BIMC 161
|
||||
#define ICBID_MASTER_SNOC_BIMC_RT 163
|
||||
#define ICBID_MASTER_SNOC_BIMC_NRT 164
|
||||
#define ICBID_MASTER_GPU_CDSP_PROC 165
|
||||
#define ICBID_MASTER_QUP_0 166
|
||||
#define ICBID_MASTER_UFS_MEM 167
|
||||
#define ICBID_MASTER_VIDEO_PROC 168
|
||||
#define ICBID_MASTER_QUP_CORE_0 170
|
||||
#define ICBID_MASTER_QUP_CORE_1 171
|
||||
#define ICBID_MASTER_CAMNOC_SF 172
|
||||
#define ICBID_MASTER_CAMNOC_HF 173
|
||||
|
||||
#define ICBID_SLAVE_EBI1 0
|
||||
#define ICBID_SLAVE_APPSS_L2 1
|
||||
#define ICBID_SLAVE_BIMC_SNOC 2
|
||||
#define ICBID_SLAVE_BIMC_SNOC_0 ICBID_SLAVE_BIMC_SNOC
|
||||
#define ICBID_SLAVE_CAMERA_CFG 3
|
||||
#define ICBID_SLAVE_DISPLAY_CFG 4
|
||||
#define ICBID_SLAVE_OCMEM_CFG 5
|
||||
#define ICBID_SLAVE_CPR_CFG 6
|
||||
#define ICBID_SLAVE_CPR_XPU_CFG 7
|
||||
#define ICBID_SLAVE_MISC_CFG 8
|
||||
#define ICBID_SLAVE_MISC_XPU_CFG 9
|
||||
#define ICBID_SLAVE_VENUS_CFG 10
|
||||
#define ICBID_SLAVE_GFX3D_CFG 11
|
||||
#define ICBID_SLAVE_MMSS_CLK_CFG 12
|
||||
#define ICBID_SLAVE_MMSS_CLK_XPU_CFG 13
|
||||
#define ICBID_SLAVE_MNOC_MPU_CFG 14
|
||||
#define ICBID_SLAVE_ONOC_MPU_CFG 15
|
||||
#define ICBID_SLAVE_MNOC_BIMC 16
|
||||
#define ICBID_SLAVE_SERVICE_MNOC 17
|
||||
#define ICBID_SLAVE_OCMEM 18
|
||||
#define ICBID_SLAVE_GMEM ICBID_SLAVE_OCMEM
|
||||
#define ICBID_SLAVE_SERVICE_ONOC 19
|
||||
#define ICBID_SLAVE_APPSS 20
|
||||
#define ICBID_SLAVE_LPASS 21
|
||||
#define ICBID_SLAVE_USB3 22
|
||||
#define ICBID_SLAVE_USB3_0 ICBID_SLAVE_USB3
|
||||
#define ICBID_SLAVE_WCSS 23
|
||||
#define ICBID_SLAVE_SNOC_BIMC 24
|
||||
#define ICBID_SLAVE_SNOC_BIMC_0 ICBID_SLAVE_SNOC_BIMC
|
||||
#define ICBID_SLAVE_SNOC_CNOC 25
|
||||
#define ICBID_SLAVE_IMEM 26
|
||||
#define ICBID_SLAVE_OCIMEM ICBID_SLAVE_IMEM
|
||||
#define ICBID_SLAVE_SNOC_OVIRT 27
|
||||
#define ICBID_SLAVE_SNOC_GVIRT ICBID_SLAVE_SNOC_OVIRT
|
||||
#define ICBID_SLAVE_SNOC_PNOC 28
|
||||
#define ICBID_SLAVE_SNOC_PCNOC ICBID_SLAVE_SNOC_PNOC
|
||||
#define ICBID_SLAVE_SERVICE_SNOC 29
|
||||
#define ICBID_SLAVE_QDSS_STM 30
|
||||
#define ICBID_SLAVE_SDCC_1 31
|
||||
#define ICBID_SLAVE_EMMC_CFG ICBID_SLAVE_SDCC_1
|
||||
#define ICBID_SLAVE_SDCC_3 32
|
||||
#define ICBID_SLAVE_SDCC_2 33
|
||||
#define ICBID_SLAVE_SDCC_4 34
|
||||
#define ICBID_SLAVE_TSIF 35
|
||||
#define ICBID_SLAVE_BAM_DMA 36
|
||||
#define ICBID_SLAVE_BLSP_2 37
|
||||
#define ICBID_SLAVE_USB_HSIC 38
|
||||
#define ICBID_SLAVE_BLSP_1 39
|
||||
#define ICBID_SLAVE_QUP_1 ICBID_SLAVE_BLSP_1
|
||||
#define ICBID_SLAVE_USB_HS 40
|
||||
#define ICBID_SLAVE_USB_HS1 ICBID_SLAVE_USB_HS
|
||||
#define ICBID_SLAVE_PDM 41
|
||||
#define ICBID_SLAVE_PERIPH_APU_CFG 42
|
||||
#define ICBID_SLAVE_PNOC_MPU_CFG 43
|
||||
#define ICBID_SLAVE_PRNG 44
|
||||
#define ICBID_SLAVE_PNOC_SNOC 45
|
||||
#define ICBID_SLAVE_PCNOC_SNOC ICBID_SLAVE_PNOC_SNOC
|
||||
#define ICBID_SLAVE_SERVICE_PNOC 46
|
||||
#define ICBID_SLAVE_CLK_CTL 47
|
||||
#define ICBID_SLAVE_CNOC_MSS 48
|
||||
#define ICBID_SLAVE_PCNOC_MSS ICBID_SLAVE_CNOC_MSS
|
||||
#define ICBID_SLAVE_SECURITY 49
|
||||
#define ICBID_SLAVE_TCSR 50
|
||||
#define ICBID_SLAVE_TLMM 51
|
||||
#define ICBID_SLAVE_CRYPTO_0_CFG 52
|
||||
#define ICBID_SLAVE_CRYPTO_1_CFG 53
|
||||
#define ICBID_SLAVE_IMEM_CFG 54
|
||||
#define ICBID_SLAVE_MESSAGE_RAM 55
|
||||
#define ICBID_SLAVE_BIMC_CFG 56
|
||||
#define ICBID_SLAVE_BOOT_ROM 57
|
||||
#define ICBID_SLAVE_CNOC_MNOC_MMSS_CFG 58
|
||||
#define ICBID_SLAVE_PMIC_ARB 59
|
||||
#define ICBID_SLAVE_SPDM_WRAPPER 60
|
||||
#define ICBID_SLAVE_DEHR_CFG 61
|
||||
#define ICBID_SLAVE_MPM 62
|
||||
#define ICBID_SLAVE_QDSS_CFG 63
|
||||
#define ICBID_SLAVE_RBCPR_CFG 64
|
||||
#define ICBID_SLAVE_RBCPR_CX_CFG ICBID_SLAVE_RBCPR_CFG
|
||||
#define ICBID_SLAVE_RBCPR_QDSS_APU_CFG 65
|
||||
#define ICBID_SLAVE_CNOC_MNOC_CFG 66
|
||||
#define ICBID_SLAVE_SNOC_MPU_CFG 67
|
||||
#define ICBID_SLAVE_CNOC_ONOC_CFG 68
|
||||
#define ICBID_SLAVE_PNOC_CFG 69
|
||||
#define ICBID_SLAVE_SNOC_CFG 70
|
||||
#define ICBID_SLAVE_EBI1_DLL_CFG 71
|
||||
#define ICBID_SLAVE_PHY_APU_CFG 72
|
||||
#define ICBID_SLAVE_EBI1_PHY_CFG 73
|
||||
#define ICBID_SLAVE_RPM 74
|
||||
#define ICBID_SLAVE_CNOC_SNOC 75
|
||||
#define ICBID_SLAVE_SERVICE_CNOC 76
|
||||
#define ICBID_SLAVE_OVIRT_SNOC 77
|
||||
#define ICBID_SLAVE_OVIRT_OCMEM 78
|
||||
#define ICBID_SLAVE_USB_HS2 79
|
||||
#define ICBID_SLAVE_QPIC 80
|
||||
#define ICBID_SLAVE_IPS_CFG 81
|
||||
#define ICBID_SLAVE_DSI_CFG 82
|
||||
#define ICBID_SLAVE_USB3_1 83
|
||||
#define ICBID_SLAVE_PCIE_0 84
|
||||
#define ICBID_SLAVE_PCIE_1 85
|
||||
#define ICBID_SLAVE_PSS_SMMU_CFG 86
|
||||
#define ICBID_SLAVE_CRYPTO_2_CFG 87
|
||||
#define ICBID_SLAVE_PCIE_0_CFG 88
|
||||
#define ICBID_SLAVE_PCIE_1_CFG 89
|
||||
#define ICBID_SLAVE_SATA_CFG 90
|
||||
#define ICBID_SLAVE_SPSS_GENI_IR 91
|
||||
#define ICBID_SLAVE_UFS_CFG 92
|
||||
#define ICBID_SLAVE_AVSYNC_CFG 93
|
||||
#define ICBID_SLAVE_VPU_CFG 94
|
||||
#define ICBID_SLAVE_USB_PHY_CFG 95
|
||||
#define ICBID_SLAVE_RBCPR_MX_CFG 96
|
||||
#define ICBID_SLAVE_PCIE_PARF 97
|
||||
#define ICBID_SLAVE_VCAP_CFG 98
|
||||
#define ICBID_SLAVE_EMAC_CFG 99
|
||||
#define ICBID_SLAVE_BCAST_CFG 100
|
||||
#define ICBID_SLAVE_KLM_CFG 101
|
||||
#define ICBID_SLAVE_DISPLAY_PWM 102
|
||||
#define ICBID_SLAVE_GENI 103
|
||||
#define ICBID_SLAVE_SNOC_BIMC_1 104
|
||||
#define ICBID_SLAVE_AUDIO 105
|
||||
#define ICBID_SLAVE_CATS_0 106
|
||||
#define ICBID_SLAVE_CATS_1 107
|
||||
#define ICBID_SLAVE_MM_INT_0 108
|
||||
#define ICBID_SLAVE_MM_INT_1 109
|
||||
#define ICBID_SLAVE_MM_INT_2 110
|
||||
#define ICBID_SLAVE_MM_INT_BIMC 111
|
||||
#define ICBID_SLAVE_MMU_MODEM_XPU_CFG 112
|
||||
#define ICBID_SLAVE_MSS_INT 113
|
||||
#define ICBID_SLAVE_PCNOC_INT_0 114
|
||||
#define ICBID_SLAVE_PCNOC_INT_1 115
|
||||
#define ICBID_SLAVE_PCNOC_M_0 116
|
||||
#define ICBID_SLAVE_PCNOC_M_1 117
|
||||
#define ICBID_SLAVE_PCNOC_S_0 118
|
||||
#define ICBID_SLAVE_PCNOC_S_1 119
|
||||
#define ICBID_SLAVE_PCNOC_S_2 120
|
||||
#define ICBID_SLAVE_PCNOC_S_3 121
|
||||
#define ICBID_SLAVE_PCNOC_S_4 122
|
||||
#define ICBID_SLAVE_PCNOC_S_6 123
|
||||
#define ICBID_SLAVE_PCNOC_S_7 124
|
||||
#define ICBID_SLAVE_PCNOC_S_8 125
|
||||
#define ICBID_SLAVE_PCNOC_S_9 126
|
||||
#define ICBID_SLAVE_PRNG_XPU_CFG 127
|
||||
#define ICBID_SLAVE_QDSS_INT 128
|
||||
#define ICBID_SLAVE_RPM_XPU_CFG 129
|
||||
#define ICBID_SLAVE_SNOC_INT_0 130
|
||||
#define ICBID_SLAVE_SNOC_INT_1 131
|
||||
#define ICBID_SLAVE_SNOC_INT_BIMC 132
|
||||
#define ICBID_SLAVE_TCU 133
|
||||
#define ICBID_SLAVE_BIMC_INT_0 134
|
||||
#define ICBID_SLAVE_BIMC_INT_1 135
|
||||
#define ICBID_SLAVE_RICA_CFG 136
|
||||
#define ICBID_SLAVE_SNOC_BIMC_2 137
|
||||
#define ICBID_SLAVE_BIMC_SNOC_1 138
|
||||
#define ICBID_SLAVE_PNOC_A1NOC 139
|
||||
#define ICBID_SLAVE_SNOC_VMEM 140
|
||||
#define ICBID_SLAVE_A0NOC_SNOC 141
|
||||
#define ICBID_SLAVE_ANOC_SNOC ICBID_SLAVE_A0NOC_SNOC
|
||||
#define ICBID_SLAVE_A1NOC_SNOC 142
|
||||
#define ICBID_SLAVE_A2NOC_SNOC 143
|
||||
#define ICBID_SLAVE_A0NOC_CFG 144
|
||||
#define ICBID_SLAVE_A0NOC_MPU_CFG 145
|
||||
#define ICBID_SLAVE_A0NOC_SMMU_CFG 146
|
||||
#define ICBID_SLAVE_A1NOC_CFG 147
|
||||
#define ICBID_SLAVE_A1NOC_MPU_CFG 148
|
||||
#define ICBID_SLAVE_A1NOC_SMMU_CFG 149
|
||||
#define ICBID_SLAVE_A2NOC_CFG 150
|
||||
#define ICBID_SLAVE_A2NOC_MPU_CFG 151
|
||||
#define ICBID_SLAVE_A2NOC_SMMU_CFG 152
|
||||
#define ICBID_SLAVE_AHB2PHY 153
|
||||
#define ICBID_SLAVE_CAMERA_THROTTLE_CFG 154
|
||||
#define ICBID_SLAVE_DCC_CFG 155
|
||||
#define ICBID_SLAVE_DISPLAY_THROTTLE_CFG 156
|
||||
#define ICBID_SLAVE_DSA_CFG 157
|
||||
#define ICBID_SLAVE_DSA_MPU_CFG 158
|
||||
#define ICBID_SLAVE_SSC_MPU_CFG 159
|
||||
#define ICBID_SLAVE_HMSS_L3 160
|
||||
#define ICBID_SLAVE_LPASS_SMMU_CFG 161
|
||||
#define ICBID_SLAVE_MMAGIC_CFG 162
|
||||
#define ICBID_SLAVE_PCIE20_AHB2PHY 163
|
||||
#define ICBID_SLAVE_PCIE_2 164
|
||||
#define ICBID_SLAVE_PCIE_2_CFG 165
|
||||
#define ICBID_SLAVE_PIMEM 166
|
||||
#define ICBID_SLAVE_PIMEM_CFG 167
|
||||
#define ICBID_SLAVE_QDSS_RBCPR_APU_CFG 168
|
||||
#define ICBID_SLAVE_RBCPR_CX 169
|
||||
#define ICBID_SLAVE_RBCPR_MX 170
|
||||
#define ICBID_SLAVE_SMMU_CPP_CFG 171
|
||||
#define ICBID_SLAVE_SMMU_JPEG_CFG 172
|
||||
#define ICBID_SLAVE_SMMU_MDP_CFG 173
|
||||
#define ICBID_SLAVE_SMMU_ROTATOR_CFG 174
|
||||
#define ICBID_SLAVE_SMMU_VENUS_CFG 175
|
||||
#define ICBID_SLAVE_SMMU_VFE_CFG 176
|
||||
#define ICBID_SLAVE_SSC_CFG 177
|
||||
#define ICBID_SLAVE_VENUS_THROTTLE_CFG 178
|
||||
#define ICBID_SLAVE_VMEM 179
|
||||
#define ICBID_SLAVE_VMEM_CFG 180
|
||||
#define ICBID_SLAVE_QDSS_MPU_CFG 181
|
||||
#define ICBID_SLAVE_USB3_PHY_CFG 182
|
||||
#define ICBID_SLAVE_IPA_CFG 183
|
||||
#define ICBID_SLAVE_PCNOC_INT_2 184
|
||||
#define ICBID_SLAVE_PCNOC_INT_3 185
|
||||
#define ICBID_SLAVE_PCNOC_INT_4 186
|
||||
#define ICBID_SLAVE_PCNOC_INT_5 187
|
||||
#define ICBID_SLAVE_PCNOC_INT_6 188
|
||||
#define ICBID_SLAVE_PCNOC_S_5 189
|
||||
#define ICBID_SLAVE_QSPI 190
|
||||
#define ICBID_SLAVE_A1NOC_MS_MPU_CFG 191
|
||||
#define ICBID_SLAVE_A2NOC_MS_MPU_CFG 192
|
||||
#define ICBID_SLAVE_MODEM_Q6_SMMU_CFG 193
|
||||
#define ICBID_SLAVE_MSS_MPU_CFG 194
|
||||
#define ICBID_SLAVE_MSS_PROC_MS_MPU_CFG 195
|
||||
#define ICBID_SLAVE_SKL 196
|
||||
#define ICBID_SLAVE_SNOC_INT_2 197
|
||||
#define ICBID_SLAVE_SMMNOC_BIMC 198
|
||||
#define ICBID_SLAVE_CRVIRT_A1NOC 199
|
||||
#define ICBID_SLAVE_SGMII 200
|
||||
#define ICBID_SLAVE_QHS4_APPS 201
|
||||
#define ICBID_SLAVE_BIMC_PCNOC 202
|
||||
#define ICBID_SLAVE_PCNOC_BIMC_1 203
|
||||
#define ICBID_SLAVE_SPMI_FETCHER 204
|
||||
#define ICBID_SLAVE_MMSS_SMMU_CFG 205
|
||||
#define ICBID_SLAVE_WLAN 206
|
||||
#define ICBID_SLAVE_CRVIRT_A2NOC 207
|
||||
#define ICBID_SLAVE_CNOC_A2NOC 208
|
||||
#define ICBID_SLAVE_GLM 209
|
||||
#define ICBID_SLAVE_GNOC_BIMC 210
|
||||
#define ICBID_SLAVE_GNOC_SNOC 211
|
||||
#define ICBID_SLAVE_QM_CFG 212
|
||||
#define ICBID_SLAVE_TLMM_EAST 213
|
||||
#define ICBID_SLAVE_TLMM_NORTH 214
|
||||
#define ICBID_SLAVE_TLMM_WEST 215
|
||||
#define ICBID_SLAVE_TLMM_SOUTH 216
|
||||
#define ICBID_SLAVE_TLMM_CENTER 217
|
||||
#define ICBID_SLAVE_MSS_NAV_CE_MPU_CFG 218
|
||||
#define ICBID_SLAVE_A2NOC_THROTTLE_CFG 219
|
||||
#define ICBID_SLAVE_CDSP 220
|
||||
#define ICBID_SLAVE_CDSP_SMMU_CFG 221
|
||||
#define ICBID_SLAVE_LPASS_MPU_CFG 222
|
||||
#define ICBID_SLAVE_CSI_PHY_CFG 223
|
||||
#define ICBID_SLAVE_DDRSS_CFG 224
|
||||
#define ICBID_SLAVE_DDRSS_MPU_CFG 225
|
||||
#define ICBID_SLAVE_SNOC_MSS_XPU_CFG 226
|
||||
#define ICBID_SLAVE_BIMC_MSS_XPU_CFG 227
|
||||
#define ICBID_SLAVE_MSS_SNOC_MPU_CFG 228
|
||||
#define ICBID_SLAVE_MSS 229
|
||||
#define ICBID_SLAVE_SDIO 230
|
||||
#define ICBID_SLAVE_QM_MPU_CFG 231
|
||||
#define ICBID_SLAVE_BIMC_SNOC_PCIE 232
|
||||
#define ICBID_SLAVE_BOOTIMEM 233
|
||||
#define ICBID_SLAVE_CDSP_CFG 234
|
||||
#define ICBID_SLAVE_WLAN_DSP_CFG 235
|
||||
#define ICBID_SLAVE_GENIR_XPU_CFG 236
|
||||
#define ICBID_SLAVE_BOOTIMEM_MPU 237
|
||||
#define ICBID_SLAVE_CRVIRT_PCNOC 238
|
||||
#define ICBID_SLAVE_WLAN_INT 239
|
||||
#define ICBID_SLAVE_WLAN_MPU_CFG 240
|
||||
#define ICBID_SLAVE_LPASS_AGNOC_CFG 241
|
||||
#define ICBID_SLAVE_LPASS_AGNOC_XPU_CFG 242
|
||||
#define ICBID_SLAVE_PLL_BIAS_CFG 243
|
||||
#define ICBID_SLAVE_EMAC 244
|
||||
#define ICBID_SLAVE_PCNOC_S_10 245
|
||||
#define ICBID_SLAVE_PCNOC_S_11 246
|
||||
#define ICBID_SLAVE_LPASS_ANOC_BIMC 247
|
||||
#define ICBID_SLAVE_SNOC_BIMC_NRT 259
|
||||
#define ICBID_SLAVE_SNOC_BIMC_RT 260
|
||||
#define ICBID_SLAVE_QUP_0 261
|
||||
#define ICBID_SLAVE_UFS_MEM_CFG 262
|
||||
#define ICBID_SLAVE_VSENSE_CTRL_CFG 263
|
||||
#define ICBID_SLAVE_QUP_CORE_0 264
|
||||
#define ICBID_SLAVE_QUP_CORE_1 265
|
||||
#define ICBID_SLAVE_GPU_CDSP_BIMC 266
|
||||
#define ICBID_SLAVE_AHB2PHY_USB 268
|
||||
#define ICBID_SLAVE_APSS_THROTTLE_CFG 270
|
||||
#define ICBID_SLAVE_CAMERA_NRT_THROTTLE_CFG 271
|
||||
#define ICBID_SLAVE_CDSP_THROTTLE_CFG 272
|
||||
#define ICBID_SLAVE_DDR_PHY_CFG 273
|
||||
#define ICBID_SLAVE_DDR_SS_CFG 274
|
||||
#define ICBID_SLAVE_GPU_CFG 275
|
||||
#define ICBID_SLAVE_GPU_THROTTLE_CFG 276
|
||||
#define ICBID_SLAVE_MAPSS 277
|
||||
#define ICBID_SLAVE_MDSP_MPU_CFG 278
|
||||
#define ICBID_SLAVE_CAMERA_RT_THROTTLE_CFG 279
|
||||
#define ICBID_SLAVE_HWKM 280
|
||||
#define ICBID_SLAVE_PKA_WRAPPER 281
|
||||
|
||||
#endif
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*/
|
||||
|
||||
@@ -2533,11 +2533,5 @@ static int __init qnoc_driver_init(void)
|
||||
}
|
||||
core_initcall(qnoc_driver_init);
|
||||
|
||||
static void __exit qnoc_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qnoc_driver);
|
||||
}
|
||||
module_exit(qnoc_driver_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SA8775P NoC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Linaro Ltd
|
||||
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@@ -2405,11 +2406,5 @@ static int __init qnoc_driver_init(void)
|
||||
}
|
||||
core_initcall(qnoc_driver_init);
|
||||
|
||||
static void __exit qnoc_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qnoc_driver);
|
||||
}
|
||||
module_exit(qnoc_driver_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm SC8280XP NoC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
1552
drivers/interconnect/qcom/sdx75.c
Normal file
1552
drivers/interconnect/qcom/sdx75.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, Linaro Limited
|
||||
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
@@ -1898,11 +1899,5 @@ static int __init qnoc_driver_init(void)
|
||||
}
|
||||
core_initcall(qnoc_driver_init);
|
||||
|
||||
static void __exit qnoc_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qnoc_driver);
|
||||
}
|
||||
module_exit(qnoc_driver_exit);
|
||||
|
||||
MODULE_DESCRIPTION("sm8450 NoC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022, Linaro Limited
|
||||
*
|
||||
*/
|
||||
@@ -2233,11 +2233,5 @@ static int __init qnoc_driver_init(void)
|
||||
}
|
||||
core_initcall(qnoc_driver_init);
|
||||
|
||||
static void __exit qnoc_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qnoc_driver);
|
||||
}
|
||||
module_exit(qnoc_driver_exit);
|
||||
|
||||
MODULE_DESCRIPTION("sm8550 NoC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
3904
drivers/interconnect/qcom/sun.c
Normal file
3904
drivers/interconnect/qcom/sun.c
Normal file
File diff suppressed because it is too large
Load Diff
52
drivers/interconnect/qcom/trace.h
Normal file
52
drivers/interconnect/qcom/trace.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM interconnect_qcom
|
||||
|
||||
#if !defined(_TRACE_INTERCONNECT_QCOM_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_INTERCONNECT_QCOM_H
|
||||
|
||||
#include <soc/qcom/tcs.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
TRACE_EVENT(bcm_voter_commit,
|
||||
|
||||
TP_PROTO(const char *rpmh_state, const struct tcs_cmd *cmd),
|
||||
|
||||
TP_ARGS(rpmh_state, cmd),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(state_name, rpmh_state)
|
||||
__field(u32, addr)
|
||||
__field(u32, data)
|
||||
__field(u32, wait)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(state_name, rpmh_state);
|
||||
__entry->addr = cmd->addr;
|
||||
__entry->data = cmd->data;
|
||||
__entry->wait = cmd->wait;
|
||||
),
|
||||
|
||||
TP_printk("%s cmd_addr=0x%x cmd_data=0x%x cmd_wait=%u",
|
||||
__get_str(state_name),
|
||||
__entry->addr,
|
||||
__entry->data,
|
||||
__entry->wait)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_INTERCONNECT_QCOM_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>
|
2812
drivers/interconnect/qcom/tuna.c
Normal file
2812
drivers/interconnect/qcom/tuna.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user