2022-07-28 11:51:57

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 00/11] soc/arm64: qcom: Add LLCC BWMON on SDM845

Hi,

Changes since v1
================
1. Patch #2: Drop also BWMON_GLOBAL_IRQ_STATUS (Sibi).
2. Minor rebasings because of above drop.
3. Patch #4: typo in subject (Sibi).
4. New patch: arm64: dts: qcom: sdm845: narrow LLCC address space (Sibi).
5. Add Rb tags.

Description
===========
BWMON is a data bandwidth monitor providing throughput/bandwidth over certain
interconnect links in a SoC. It might be used to gather current bus usage and
vote for interconnect bandwidth, thus adjusting the bus speed based on actual
usage.

Qualcomm SoCs might several BWMON instances. Extend existing support for CPU
BWMON (called v4) to LLCC BWMON (called v5).

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>

Best regards,
Krzysztof

Krzysztof Kozlowski (11):
dt-bindings: interconnect: qcom,msm8998-bwmon: add support for SDM845
LLCC BWMON
soc: qcom: icc-bwmon: re-use IRQ enable/clear define
soc: qcom: icc-bwmon: drop unused registers
soc: qcom: icc-bwmon: store reference to variant data in container
soc: qcom: icc-bwmon: clear all registers on init
soc: qcom: icc-bwmon: store count unit per variant
soc: qcom: icc-bwmon: use regmap and prepare for BWMON v5
soc: qcom: icc-bwmon: add per-variant quirks
soc: qcom: icc-bwmon: add support for SDM845 LLCC BWMON
arm64: dts: qcom: sdm845: narrow LLCC address space
arm64: dts: qcom: sdm845: add LLCC BWMON

.../interconnect/qcom,msm8998-bwmon.yaml | 1 +
arch/arm64/boot/dts/qcom/sdm845.dtsi | 39 +-
drivers/soc/qcom/icc-bwmon.c | 460 ++++++++++++++----
3 files changed, 401 insertions(+), 99 deletions(-)

--
2.34.1


2022-07-28 11:53:04

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 02/11] soc: qcom: icc-bwmon: re-use IRQ enable/clear define

The interrupt enable, status and clear registers have the same layout,
so BWMON_GLOBAL_IRQ_ENABLE_ENABLE define can be used also for clearing
IRQ, instead of hard-coded value.

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
Reviewed-by: Sibi Sankar <[email protected]>
---
drivers/soc/qcom/icc-bwmon.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index bea3ea1de7a4..3415f42523cd 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -162,7 +162,8 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon)
* interrupt is cleared.
*/
writel(BWMON_IRQ_ENABLE_MASK, bwmon->base + BWMON_IRQ_CLEAR);
- writel(BIT(0), bwmon->base + BWMON_GLOBAL_IRQ_CLEAR);
+ writel(BWMON_GLOBAL_IRQ_ENABLE_ENABLE,
+ bwmon->base + BWMON_GLOBAL_IRQ_CLEAR);
}

static void bwmon_disable(struct icc_bwmon *bwmon)
--
2.34.1

2022-07-28 12:20:45

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 01/11] dt-bindings: interconnect: qcom,msm8998-bwmon: add support for SDM845 LLCC BWMON

Add compatible for SDM845 Bandwidth Monitor instance measuring traffic
between LLCC and memory. It comes with different register layout:
called v5.

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
Acked-by: Rob Herring <[email protected]>
Reviewed-by: Sibi Sankar <[email protected]>
---
.../devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
index c2e697f6e6cf..32e2892d736b 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
@@ -27,6 +27,7 @@ properties:
- qcom,sdm845-bwmon
- const: qcom,msm8998-bwmon
- const: qcom,msm8998-bwmon # BWMON v4
+ - const: qcom,sdm845-llcc-bwmon # BWMON v5

interconnects:
maxItems: 1
--
2.34.1

2022-07-28 12:20:46

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 10/11] arm64: dts: qcom: sdm845: narrow LLCC address space

The Last Level Cache Controller (LLCC) device does not need to access
entire LLCC address space. Currently driver uses only hardware info and
status registers which both reside in LLCC0_COMMON range (offset
0x30000, size 0x1000). Narrow the address space to allow binding other
drivers to rest of LLCC address space.

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>
Reported-by: Steev Klimaszewski <[email protected]>
Suggested-by: Sibi Sankar <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index fe14f7e7523b..e318c3f8aee0 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -2048,7 +2048,7 @@ uart15: serial@a9c000 {

llcc: system-cache-controller@1100000 {
compatible = "qcom,sdm845-llcc";
- reg = <0 0x01100000 0 0x200000>, <0 0x01300000 0 0x50000>;
+ reg = <0 0x01100000 0 0x31000>, <0 0x01300000 0 0x50000>;
reg-names = "llcc_base", "llcc_broadcast_base";
interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
};
--
2.34.1

2022-07-28 12:21:59

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 05/11] soc: qcom: icc-bwmon: clear all registers on init

The hardware programming guide recommends to clear all registers on
first initialization, through separate field in BWMON_CLEAR register.

This makes sense in general but especially if driver is rebound to avoid
spurious/early interrupts.

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/soc/qcom/icc-bwmon.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index a820855e85b4..d2df8feff651 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -50,6 +50,7 @@

#define BWMON_CLEAR 0x2a4
#define BWMON_CLEAR_CLEAR BIT(0)
+#define BWMON_CLEAR_CLEAR_ALL BIT(1)

#define BWMON_SAMPLE_WINDOW 0x2a8
#define BWMON_THRESHOLD_HIGH 0x2ac
@@ -127,8 +128,12 @@ struct icc_bwmon {
unsigned int current_kbps;
};

-static void bwmon_clear_counters(struct icc_bwmon *bwmon)
+static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
{
+ unsigned int val = BWMON_CLEAR_CLEAR;
+
+ if (clear_all)
+ val |= BWMON_CLEAR_CLEAR_ALL;
/*
* Clear counters. The order and barriers are
* important. Quoting downstream Qualcomm msm-4.9 tree:
@@ -137,7 +142,7 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon)
* region. So, we need to make sure the counter clear is completed
* before we try to clear the IRQ or do any other counter operations.
*/
- writel(BWMON_CLEAR_CLEAR, bwmon->base + BWMON_CLEAR);
+ writel(val, bwmon->base + BWMON_CLEAR);
}

static void bwmon_clear_irq(struct icc_bwmon *bwmon)
@@ -208,7 +213,7 @@ static void bwmon_start(struct icc_bwmon *bwmon)
unsigned int thres_count;
int window;

- bwmon_clear_counters(bwmon);
+ bwmon_clear_counters(bwmon, true);

window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
/* Maximum sampling window: 0xfffff */
@@ -304,7 +309,7 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, up_kbps);
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, down_kbps);
/* Write barriers in bwmon_clear_counters() */
- bwmon_clear_counters(bwmon);
+ bwmon_clear_counters(bwmon, false);
bwmon_clear_irq(bwmon);
bwmon_enable(bwmon, irq_enable);

--
2.34.1

2022-07-28 12:22:02

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 08/11] soc: qcom: icc-bwmon: add per-variant quirks

BWMON v5 lacks global interrupt registers. Other BWMON versions differ
as well, so add quirks for easier customization of code flow.

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/soc/qcom/icc-bwmon.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index 058c35d8dbbe..2e4a0fdfbf54 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -100,6 +100,9 @@

#define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone))

+/* Quirks for specific BWMON types */
+#define BWMON_HAS_GLOBAL_IRQ BIT(0)
+
enum bwmon_fields {
F_GLOBAL_IRQ_CLEAR,
F_GLOBAL_IRQ_ENABLE,
@@ -136,6 +139,7 @@ struct icc_bwmon_data {
unsigned int default_lowbw_kbps;
u8 zone1_thres_count;
u8 zone3_thres_count;
+ unsigned int quirks;

const struct regmap_config *regmap_cfg;
const struct reg_field *regmap_fields;
@@ -270,14 +274,16 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon)
* interrupt is cleared.
*/
regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK);
- regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR],
- BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
+ if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
+ regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR],
+ BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
}

static void bwmon_disable(struct icc_bwmon *bwmon)
{
/* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
- regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0);
+ if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
+ regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0);
regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0);

/*
@@ -290,8 +296,9 @@ static void bwmon_disable(struct icc_bwmon *bwmon)
static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
{
/* Enable interrupts */
- regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE],
- BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
+ if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
+ regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE],
+ BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable);

/* Enable bwmon */
@@ -543,6 +550,7 @@ static const struct icc_bwmon_data msm8998_bwmon_data = {
.default_lowbw_kbps = 0,
.zone1_thres_count = 16,
.zone3_thres_count = 1,
+ .quirks = BWMON_HAS_GLOBAL_IRQ,
.regmap_fields = msm8998_bwmon_reg_fields,
.regmap_cfg = &msm8998_bwmon_regmap_cfg,
};
--
2.34.1

2022-07-28 12:23:12

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH v2 04/11] soc: qcom: icc-bwmon: store reference to variant data in container

Instead of copying pieces of variant-specific data (struct
icc_bwmon_data) into the state container (struct icc_bwmon), just store
a pointer to it.

This simplifies a bit the code and allows later to grow easily the
variant-specific data for new BWMON v5.

Cc: Rajendra Nayak <[email protected]>
Cc: Sibi Sankar <[email protected]>
Signed-off-by: Krzysztof Kozlowski <[email protected]>
Reviewed-by: Sibi Sankar <[email protected]>
---
drivers/soc/qcom/icc-bwmon.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index 9295ea04356a..a820855e85b4 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -117,11 +117,10 @@ struct icc_bwmon_data {

struct icc_bwmon {
struct device *dev;
+ const struct icc_bwmon_data *data;
void __iomem *base;
int irq;

- unsigned int default_lowbw_kbps;
- unsigned int sample_ms;
unsigned int max_bw_kbps;
unsigned int min_bw_kbps;
unsigned int target_kbps;
@@ -198,20 +197,20 @@ static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg,
{
unsigned int thres;

- thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->sample_ms,
+ thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->data->sample_ms,
MSEC_PER_SEC);
writel_relaxed(thres, bwmon->base + reg);
}

-static void bwmon_start(struct icc_bwmon *bwmon,
- const struct icc_bwmon_data *data)
+static void bwmon_start(struct icc_bwmon *bwmon)
{
+ const struct icc_bwmon_data *data = bwmon->data;
unsigned int thres_count;
int window;

bwmon_clear_counters(bwmon);

- window = mult_frac(bwmon->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
+ window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
/* Maximum sampling window: 0xfffff */
writel_relaxed(window, bwmon->base + BWMON_SAMPLE_WINDOW);

@@ -266,7 +265,7 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id)
*/
max = readl(bwmon->base + BWMON_ZONE_MAX(zone)) + 1;
max *= BWMON_COUNT_UNIT_KB;
- bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->sample_ms);
+ bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);

return IRQ_WAKE_THREAD;
}
@@ -328,14 +327,13 @@ static int bwmon_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct dev_pm_opp *opp;
struct icc_bwmon *bwmon;
- const struct icc_bwmon_data *data;
int ret;

bwmon = devm_kzalloc(dev, sizeof(*bwmon), GFP_KERNEL);
if (!bwmon)
return -ENOMEM;

- data = of_device_get_match_data(dev);
+ bwmon->data = of_device_get_match_data(dev);

bwmon->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bwmon->base)) {
@@ -363,8 +361,6 @@ static int bwmon_probe(struct platform_device *pdev)
if (IS_ERR(opp))
return dev_err_probe(dev, ret, "failed to find min peak bandwidth\n");

- bwmon->sample_ms = data->sample_ms;
- bwmon->default_lowbw_kbps = data->default_lowbw_kbps;
bwmon->dev = dev;

bwmon_disable(bwmon);
@@ -375,7 +371,7 @@ static int bwmon_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "failed to request IRQ\n");

platform_set_drvdata(pdev, bwmon);
- bwmon_start(bwmon, data);
+ bwmon_start(bwmon);

return 0;
}
--
2.34.1

2022-07-29 14:41:51

by Steev Klimaszewski

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] soc/arm64: qcom: Add LLCC BWMON on SDM845

Hi,

On 7/28/22 6:37 AM, Krzysztof Kozlowski wrote:
> Hi,
>
> Changes since v1
> ================
> 1. Patch #2: Drop also BWMON_GLOBAL_IRQ_STATUS (Sibi).
> 2. Minor rebasings because of above drop.
> 3. Patch #4: typo in subject (Sibi).
> 4. New patch: arm64: dts: qcom: sdm845: narrow LLCC address space (Sibi).
> 5. Add Rb tags.
>
> Description
> ===========
> BWMON is a data bandwidth monitor providing throughput/bandwidth over certain
> interconnect links in a SoC. It might be used to gather current bus usage and
> vote for interconnect bandwidth, thus adjusting the bus speed based on actual
> usage.
>
> Qualcomm SoCs might several BWMON instances. Extend existing support for CPU
> BWMON (called v4) to LLCC BWMON (called v5).
>
> Cc: Rajendra Nayak <[email protected]>
> Cc: Sibi Sankar <[email protected]>
>
> Best regards,
> Krzysztof
>
> Krzysztof Kozlowski (11):
> dt-bindings: interconnect: qcom,msm8998-bwmon: add support for SDM845
> LLCC BWMON
> soc: qcom: icc-bwmon: re-use IRQ enable/clear define
> soc: qcom: icc-bwmon: drop unused registers
> soc: qcom: icc-bwmon: store reference to variant data in container
> soc: qcom: icc-bwmon: clear all registers on init
> soc: qcom: icc-bwmon: store count unit per variant
> soc: qcom: icc-bwmon: use regmap and prepare for BWMON v5
> soc: qcom: icc-bwmon: add per-variant quirks
> soc: qcom: icc-bwmon: add support for SDM845 LLCC BWMON
> arm64: dts: qcom: sdm845: narrow LLCC address space
> arm64: dts: qcom: sdm845: add LLCC BWMON
>
> .../interconnect/qcom,msm8998-bwmon.yaml | 1 +
> arch/arm64/boot/dts/qcom/sdm845.dtsi | 39 +-
> drivers/soc/qcom/icc-bwmon.c | 460 ++++++++++++++----
> 3 files changed, 401 insertions(+), 99 deletions(-)
>
Tested on the Lenovo Yoga C630 with QCOM_LLCC=m and no longer see the
previous error message.

Tested-by: Steev Klimaszewski <[email protected]>