From fcc936537bb29a273415cf24f57d8e63c869597b Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Thu, 2 Apr 2020 18:00:33 -0700 Subject: [PATCH 1/2] dt-bindings: interconnect: Update SLAVE_EPSS_L3_SHARED Update the SLAVE_EPSS_L3_SHARED binding to share the same number space as the rest of the EPSS bindings. This allows for the same provider to be used for all of them. Change-Id: I4e0bd80388945f7a9f897270de081d2ba87701a8 Signed-off-by: Mike Tipton --- include/dt-bindings/interconnect/qcom,epss-l3.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/dt-bindings/interconnect/qcom,epss-l3.h b/include/dt-bindings/interconnect/qcom,epss-l3.h index 34cca76988e2..e52fe20bd116 100644 --- a/include/dt-bindings/interconnect/qcom,epss-l3.h +++ b/include/dt-bindings/interconnect/qcom,epss-l3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef __DT_BINDINGS_INTERCONNECT_QCOM_EPSS_L3_H @@ -15,7 +15,6 @@ #define SLAVE_EPSS_L3_CPU5 6 #define SLAVE_EPSS_L3_CPU6 7 #define SLAVE_EPSS_L3_CPU7 8 - -#define SLAVE_EPSS_L3_SHARED 0 +#define SLAVE_EPSS_L3_SHARED 9 #endif From 9a0e01dec1022b4a0b71e0ac1090d1027553bd01 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Thu, 2 Apr 2020 18:00:33 -0700 Subject: [PATCH 2/2] interconnect: qcom: Fix BW requests to L3_SHARED returning -EINVAL The qcom,lahaina-epss-l3-shared provider currently only defines a single endpoint: SLAVE_EPSS_L3_SHARED. The framework only calls the set() callback for pairs of nodes. If there is no valid pair belonging to the provider, then apply_constraints() and icc_set_bw() will return -EINVAL. The lahaina-epss-l3-shared provider would need an additional master endpoint for these requests to work. However, even if that problem is fixed, there's another problem in qcom_icc_l3_shared_set() that prevents the requested level from taking effect in HW. This function writes the required level into the PERF_STATE_DESIRED register, which is ignored when per-CPU L3 voting is enabled in HW. When per-CPU L3 voting is enabled, only the L3_VOTE register is counted. To fix both of these problems, just remove the separate qcom,lahaina-epss-l3-shared provider entirely and move SLAVE_EPSS_L3_SHARED as an endpoint on qcom,lahaina-epss-l3-cpu. The qcom_icc_l3_cpu_set() function uses the L3_VOTE register and can be used for the shared L3 vote as-is. The only reason we'd ever need to use PERF_STATE_DESIRED is if per-CPU L3 voting is disabled, but that will likely never happen. All use cases can already be supported with per-CPU voting enabled (per-CPU, shared, or a mix of both). Change-Id: Ia67aadf26896a3a819aba8f2e4196d78d0c5c1f5 Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/epss-l3.c | 39 ++--------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/drivers/interconnect/qcom/epss-l3.c b/drivers/interconnect/qcom/epss-l3.c index 6a7e167134cf..ac6babf6856f 100644 --- a/drivers/interconnect/qcom/epss-l3.c +++ b/drivers/interconnect/qcom/epss-l3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * */ @@ -121,6 +121,7 @@ static struct qcom_icc_node *lahaina_epss_l3_nodes[] = { [SLAVE_EPSS_L3_CPU5] = &slv_epss_l3_cpu5, [SLAVE_EPSS_L3_CPU6] = &slv_epss_l3_cpu6, [SLAVE_EPSS_L3_CPU7] = &slv_epss_l3_cpu7, + [SLAVE_EPSS_L3_SHARED] = &slv_epss_l3_shared, }; static struct qcom_icc_desc lahaina_epss_l3 = { @@ -128,15 +129,6 @@ static struct qcom_icc_desc lahaina_epss_l3 = { .num_nodes = ARRAY_SIZE(lahaina_epss_l3_nodes), }; -static struct qcom_icc_node *lahaina_epss_l3_shared_nodes[] = { - [SLAVE_EPSS_L3_SHARED] = &slv_epss_l3_shared, -}; - -static struct qcom_icc_desc lahaina_epss_l3_shared = { - .nodes = lahaina_epss_l3_shared_nodes, - .num_nodes = ARRAY_SIZE(lahaina_epss_l3_shared_nodes), -}; - static int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, u32 peak_bw, u32 *agg_avg, u32 *agg_peak) { @@ -169,29 +161,6 @@ static int qcom_icc_l3_cpu_set(struct icc_node *src, struct icc_node *dst) return 0; } -static int qcom_icc_l3_shared_set(struct icc_node *src, struct icc_node *dst) -{ - struct qcom_epss_l3_icc_provider *qp; - struct icc_provider *provider; - struct qcom_icc_node *qn; - unsigned int index; - u64 rate; - - qn = dst->data; - provider = src->provider; - qp = to_qcom_provider(provider); - - rate = dst->peak_bw; - - for (index = 0; index < qp->max_state; index++) { - if (qp->lut_freqs[index] >= rate) - break; - } - - writel_relaxed(index, qp->base + REG_PERF_STATE); - return 0; -} - static int qcom_epss_l3_remove(struct platform_device *pdev) { struct qcom_epss_l3_icc_provider *qp = platform_get_drvdata(pdev); @@ -292,8 +261,6 @@ static int qcom_epss_l3_probe(struct platform_device *pdev) compat = of_get_property(pdev->dev.of_node, "compatible", &compatlen); if (!compat || (compatlen <= 0)) return -EINVAL; - if (!strcmp(compat, "qcom,lahaina-epss-l3-shared")) - provider->set = qcom_icc_l3_shared_set; ret = icc_provider_add(provider); if (ret) { @@ -335,8 +302,6 @@ err: static const struct of_device_id epss_l3_of_match[] = { { .compatible = "qcom,lahaina-epss-l3-cpu", .data = &lahaina_epss_l3 }, - { .compatible = "qcom,lahaina-epss-l3-shared", - .data = &lahaina_epss_l3_shared }, { }, }; MODULE_DEVICE_TABLE(of, epss_l3_of_match);