sunxi: backport Allwinner H616 DVFS support

Backport H616 DVFS support from linux-next.
Tested on the Orange Pi Zero 3 (H618 SoC).

Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Link: https://github.com/openwrt/openwrt/pull/15600
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Chukun Pan 2024-05-27 23:18:01 +08:00 committed by Hauke Mehrtens
parent dad6ac5e34
commit be71e16630
9 changed files with 823 additions and 0 deletions

View File

@ -0,0 +1,32 @@
From 9cf3415ade2d7598d78d2ce6d35d6d6d06132201 Mon Sep 17 00:00:00 2001
From: Martin Botka <martin.botka@somainline.org>
Date: Thu, 18 Apr 2024 16:44:01 +0100
Subject: [PATCH] firmware: smccc: Export revision soc_id function
The "SoC ID revision" as provided via the SMCCC SOCID interface can be
valuable information for drivers, when certain functionality depends
on a die revision, for instance.
One example is the sun50i-cpufreq-nvmem driver, which needs this
information to determine the speed bin of the SoC.
Export the arm_smccc_get_soc_id_revision() function so that it can be
called by any driver.
Signed-off-by: Martin Botka <martin.botka@somainline.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/firmware/smccc/smccc.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/firmware/smccc/smccc.c
+++ b/drivers/firmware/smccc/smccc.c
@@ -69,6 +69,7 @@ s32 arm_smccc_get_soc_id_revision(void)
{
return smccc_soc_id_revision;
}
+EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
static int __init smccc_devices_init(void)
{

View File

@ -0,0 +1,29 @@
From 6ae07744cf334b750762ba881492c0cfba524b38 Mon Sep 17 00:00:00 2001
From: Martin Botka <martin.botka@somainline.org>
Date: Thu, 18 Apr 2024 16:44:02 +0100
Subject: [PATCH] cpufreq: dt-platdev: Blocklist Allwinner H616/618 SoCs
The AllWinner H616 SoC will use the (extended) H6 OPP driver, so add
them to the cpufreq-dt blocklist, to not create the device twice.
This also affects the closely related sibling SoCs H618 and H700.
Signed-off-by: Martin Botka <martin.botka@somainline.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/cpufreq-dt-platdev.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -104,6 +104,9 @@ static const struct of_device_id allowli
*/
static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "allwinner,sun50i-h6", },
+ { .compatible = "allwinner,sun50i-h616", },
+ { .compatible = "allwinner,sun50i-h618", },
+ { .compatible = "allwinner,sun50i-h700", },
{ .compatible = "apple,arm-platform", },

View File

@ -0,0 +1,149 @@
From 6cc4bcceff9af0e6be9738096d95e4ba75e75123 Mon Sep 17 00:00:00 2001
From: Brandon Cheo Fusi <fusibrandon13@gmail.com>
Date: Thu, 18 Apr 2024 16:44:04 +0100
Subject: [PATCH] cpufreq: sun50i: Refactor speed bin decoding
Make converting the speed bin value into a speed grade generic and
determined by a platform specific callback. Also change the prototypes
involved to encode the speed bin directly in the return value.
This allows to extend the driver more easily to support more SoCs.
Signed-off-by: Brandon Cheo Fusi <fusibrandon13@gmail.com>
[Andre: merge output into return value]
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/sun50i-cpufreq-nvmem.c | 74 +++++++++++++++++---------
1 file changed, 49 insertions(+), 25 deletions(-)
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -25,19 +25,52 @@
static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
+struct sunxi_cpufreq_data {
+ u32 (*efuse_xlate)(u32 speedbin);
+};
+
+static u32 sun50i_h6_efuse_xlate(u32 speedbin)
+{
+ u32 efuse_value;
+
+ efuse_value = (speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
+
+ /*
+ * We treat unexpected efuse values as if the SoC was from
+ * the slowest bin. Expected efuse values are 1-3, slowest
+ * to fastest.
+ */
+ if (efuse_value >= 1 && efuse_value <= 3)
+ return efuse_value - 1;
+ else
+ return 0;
+}
+
+static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
+ .efuse_xlate = sun50i_h6_efuse_xlate,
+};
+
+static const struct of_device_id cpu_opp_match_list[] = {
+ { .compatible = "allwinner,sun50i-h6-operating-points",
+ .data = &sun50i_h6_cpufreq_data,
+ },
+ {}
+};
+
/**
* sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
- * @versions: Set to the value parsed from efuse
*
- * Returns 0 if success.
+ * Returns non-negative speed bin index on success, a negative error
+ * value otherwise.
*/
-static int sun50i_cpufreq_get_efuse(u32 *versions)
+static int sun50i_cpufreq_get_efuse(void)
{
+ const struct sunxi_cpufreq_data *opp_data;
struct nvmem_cell *speedbin_nvmem;
+ const struct of_device_id *match;
struct device_node *np;
struct device *cpu_dev;
- u32 *speedbin, efuse_value;
- size_t len;
+ u32 *speedbin;
int ret;
cpu_dev = get_cpu_device(0);
@@ -48,12 +81,12 @@ static int sun50i_cpufreq_get_efuse(u32
if (!np)
return -ENOENT;
- ret = of_device_is_compatible(np,
- "allwinner,sun50i-h6-operating-points");
- if (!ret) {
+ match = of_match_node(cpu_opp_match_list, np);
+ if (!match) {
of_node_put(np);
return -ENOENT;
}
+ opp_data = match->data;
speedbin_nvmem = of_nvmem_cell_get(np, NULL);
of_node_put(np);
@@ -61,25 +94,16 @@ static int sun50i_cpufreq_get_efuse(u32
return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
"Could not get nvmem cell\n");
- speedbin = nvmem_cell_read(speedbin_nvmem, &len);
+ speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
nvmem_cell_put(speedbin_nvmem);
if (IS_ERR(speedbin))
return PTR_ERR(speedbin);
- efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
-
- /*
- * We treat unexpected efuse values as if the SoC was from
- * the slowest bin. Expected efuse values are 1-3, slowest
- * to fastest.
- */
- if (efuse_value >= 1 && efuse_value <= 3)
- *versions = efuse_value - 1;
- else
- *versions = 0;
+ ret = opp_data->efuse_xlate(*speedbin);
kfree(speedbin);
- return 0;
+
+ return ret;
};
static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
@@ -87,7 +111,7 @@ static int sun50i_cpufreq_nvmem_probe(st
int *opp_tokens;
char name[MAX_NAME_LEN];
unsigned int cpu;
- u32 speed = 0;
+ int speed;
int ret;
opp_tokens = kcalloc(num_possible_cpus(), sizeof(*opp_tokens),
@@ -95,10 +119,10 @@ static int sun50i_cpufreq_nvmem_probe(st
if (!opp_tokens)
return -ENOMEM;
- ret = sun50i_cpufreq_get_efuse(&speed);
- if (ret) {
+ speed = sun50i_cpufreq_get_efuse();
+ if (speed < 0) {
kfree(opp_tokens);
- return ret;
+ return speed;
}
snprintf(name, MAX_NAME_LEN, "speed%d", speed);

View File

@ -0,0 +1,132 @@
From fa5aec9561cfc4f4370983ca5818c90227c9d90e Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@arm.com>
Date: Thu, 18 Apr 2024 16:44:05 +0100
Subject: [PATCH] cpufreq: sun50i: Add support for opp_supported_hw
The opp_supported_hw DT property allows the DT to specify a mask of chip
revisions that a certain OPP is eligible for. This allows for easy
limiting of maximum frequencies, for instance.
Add support for that in the sun50i-cpufreq-nvmem driver. We support both
the existing opp-microvolt suffix properties as well as the
opp-supported-hw property, the generic code figures out which is needed
automatically.
However if none of the DT OPP nodes contain an opp-supported-hw
property, the core code will ignore all OPPs and the driver will fail
probing. So check the DT's eligibility first before using that feature.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/sun50i-cpufreq-nvmem.c | 62 ++++++++++++++++++++++----
1 file changed, 54 insertions(+), 8 deletions(-)
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -58,6 +58,41 @@ static const struct of_device_id cpu_opp
};
/**
+ * dt_has_supported_hw() - Check if any OPPs use opp-supported-hw
+ *
+ * If we ask the cpufreq framework to use the opp-supported-hw feature, it
+ * will ignore every OPP node without that DT property. If none of the OPPs
+ * have it, the driver will fail probing, due to the lack of OPPs.
+ *
+ * Returns true if we have at least one OPP with the opp-supported-hw property.
+ */
+static bool dt_has_supported_hw(void)
+{
+ bool has_opp_supported_hw = false;
+ struct device_node *np, *opp;
+ struct device *cpu_dev;
+
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev)
+ return -ENODEV;
+
+ np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+ if (!np)
+ return -ENOENT;
+
+ for_each_child_of_node(np, opp) {
+ if (of_find_property(opp, "opp-supported-hw", NULL)) {
+ has_opp_supported_hw = true;
+ break;
+ }
+ }
+
+ of_node_put(np);
+
+ return has_opp_supported_hw;
+}
+
+/**
* sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
*
* Returns non-negative speed bin index on success, a negative error
@@ -110,7 +145,8 @@ static int sun50i_cpufreq_nvmem_probe(st
{
int *opp_tokens;
char name[MAX_NAME_LEN];
- unsigned int cpu;
+ unsigned int cpu, supported_hw;
+ struct dev_pm_opp_config config = {};
int speed;
int ret;
@@ -125,7 +161,18 @@ static int sun50i_cpufreq_nvmem_probe(st
return speed;
}
+ /*
+ * We need at least one OPP with the "opp-supported-hw" property,
+ * or else the upper layers will ignore every OPP and will bail out.
+ */
+ if (dt_has_supported_hw()) {
+ supported_hw = 1U << speed;
+ config.supported_hw = &supported_hw;
+ config.supported_hw_count = 1;
+ }
+
snprintf(name, MAX_NAME_LEN, "speed%d", speed);
+ config.prop_name = name;
for_each_possible_cpu(cpu) {
struct device *cpu_dev = get_cpu_device(cpu);
@@ -135,12 +182,11 @@ static int sun50i_cpufreq_nvmem_probe(st
goto free_opp;
}
- opp_tokens[cpu] = dev_pm_opp_set_prop_name(cpu_dev, name);
- if (opp_tokens[cpu] < 0) {
- ret = opp_tokens[cpu];
- pr_err("Failed to set prop name\n");
+ ret = dev_pm_opp_set_config(cpu_dev, &config);
+ if (ret < 0)
goto free_opp;
- }
+
+ opp_tokens[cpu] = ret;
}
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
@@ -155,7 +201,7 @@ static int sun50i_cpufreq_nvmem_probe(st
free_opp:
for_each_possible_cpu(cpu)
- dev_pm_opp_put_prop_name(opp_tokens[cpu]);
+ dev_pm_opp_clear_config(opp_tokens[cpu]);
kfree(opp_tokens);
return ret;
@@ -169,7 +215,7 @@ static void sun50i_cpufreq_nvmem_remove(
platform_device_unregister(cpufreq_dt_pdev);
for_each_possible_cpu(cpu)
- dev_pm_opp_put_prop_name(opp_tokens[cpu]);
+ dev_pm_opp_clear_config(opp_tokens[cpu]);
kfree(opp_tokens);
}

View File

@ -0,0 +1,122 @@
From e2e2dcd2e944fe6167cb731864f8a1343f1bbee7 Mon Sep 17 00:00:00 2001
From: Martin Botka <martin.botka@somainline.org>
Date: Thu, 18 Apr 2024 16:44:06 +0100
Subject: [PATCH] cpufreq: sun50i: Add H616 support
The Allwinner H616/H618 SoCs have different OPP tables per SoC version
and die revision. The SoC version is stored in NVMEM, as before, though
encoded differently. The die revision is in a different register, in the
SRAM controller. Firmware already exports that value in a standardised
way, through the SMCCC SoCID mechanism. We need both values, as some chips
have the same SoC version, but they don't support the same frequencies and
they get differentiated by the die revision.
Add the new compatible string and tie the new translation function to
it. This mechanism not only covers the original H616 SoC, but also its
very close sibling SoCs H618 and H700, so add them to the list as well.
Signed-off-by: Martin Botka <martin.botka@somainline.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/sun50i-cpufreq-nvmem.c | 67 ++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -10,6 +10,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/arm-smccc.h>
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
@@ -46,14 +47,77 @@ static u32 sun50i_h6_efuse_xlate(u32 spe
return 0;
}
+static int get_soc_id_revision(void)
+{
+#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
+ return arm_smccc_get_soc_id_revision();
+#else
+ return SMCCC_RET_NOT_SUPPORTED;
+#endif
+}
+
+/*
+ * Judging by the OPP tables in the vendor BSP, the quality order of the
+ * returned speedbin index is 4 -> 0/2 -> 3 -> 1, from worst to best.
+ * 0 and 2 seem identical from the OPP tables' point of view.
+ */
+static u32 sun50i_h616_efuse_xlate(u32 speedbin)
+{
+ int ver_bits = get_soc_id_revision();
+ u32 value = 0;
+
+ switch (speedbin & 0xffff) {
+ case 0x2000:
+ value = 0;
+ break;
+ case 0x2400:
+ case 0x7400:
+ case 0x2c00:
+ case 0x7c00:
+ if (ver_bits != SMCCC_RET_NOT_SUPPORTED && ver_bits <= 1) {
+ /* ic version A/B */
+ value = 1;
+ } else {
+ /* ic version C and later version */
+ value = 2;
+ }
+ break;
+ case 0x5000:
+ case 0x5400:
+ case 0x6000:
+ value = 3;
+ break;
+ case 0x5c00:
+ value = 4;
+ break;
+ case 0x5d00:
+ value = 0;
+ break;
+ default:
+ pr_warn("sun50i-cpufreq-nvmem: unknown speed bin 0x%x, using default bin 0\n",
+ speedbin & 0xffff);
+ value = 0;
+ break;
+ }
+
+ return value;
+}
+
static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
.efuse_xlate = sun50i_h6_efuse_xlate,
};
+static struct sunxi_cpufreq_data sun50i_h616_cpufreq_data = {
+ .efuse_xlate = sun50i_h616_efuse_xlate,
+};
+
static const struct of_device_id cpu_opp_match_list[] = {
{ .compatible = "allwinner,sun50i-h6-operating-points",
.data = &sun50i_h6_cpufreq_data,
},
+ { .compatible = "allwinner,sun50i-h616-operating-points",
+ .data = &sun50i_h616_cpufreq_data,
+ },
{}
};
@@ -230,6 +294,9 @@ static struct platform_driver sun50i_cpu
static const struct of_device_id sun50i_cpufreq_match_list[] = {
{ .compatible = "allwinner,sun50i-h6" },
+ { .compatible = "allwinner,sun50i-h616" },
+ { .compatible = "allwinner,sun50i-h618" },
+ { .compatible = "allwinner,sun50i-h700" },
{}
};
MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list);

View File

@ -0,0 +1,188 @@
From 3e057e05b3b281bcc29db573eb51f87ee6b5afc0 Mon Sep 17 00:00:00 2001
From: Martin Botka <martin.botka@somainline.org>
Date: Thu, 18 Apr 2024 16:44:07 +0100
Subject: [PATCH] arm64: dts: allwinner: h616: Add CPU OPPs table
Add an Operating Performance Points table for the CPU cores to enable
Dynamic Voltage & Frequency Scaling (DVFS) on the H616.
The values were taken from the BSP sources. There is a separate OPP set
seen on some H700 devices, but they didn't really work out in testing, so
they are not included for now.
Also add the needed cpu_speed_grade nvmem cell and the cooling cells
properties, to enable passive cooling.
Signed-off-by: Martin Botka <martin.botka@somainline.org>
[Andre: rework to minimise opp-microvolt properties]
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
.../dts/allwinner/sun50i-h616-cpu-opp.dtsi | 115 ++++++++++++++++++
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 8 ++
2 files changed, 123 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2023 Martin Botka <martin@somainline.org>
+
+/ {
+ cpu_opp_table: opp-table-cpu {
+ compatible = "allwinner,sun50i-h616-operating-points";
+ nvmem-cells = <&cpu_speed_grade>;
+ opp-shared;
+
+ opp-480000000 {
+ opp-hz = /bits/ 64 <480000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x1f>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x12>;
+ };
+
+ opp-720000000 {
+ opp-hz = /bits/ 64 <720000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x0d>;
+ };
+
+ opp-792000000 {
+ opp-hz = /bits/ 64 <792000000>;
+ opp-microvolt-speed1 = <900000>;
+ opp-microvolt-speed4 = <940000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x12>;
+ };
+
+ opp-936000000 {
+ opp-hz = /bits/ 64 <936000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x0d>;
+ };
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt-speed0 = <950000>;
+ opp-microvolt-speed1 = <940000>;
+ opp-microvolt-speed2 = <950000>;
+ opp-microvolt-speed3 = <950000>;
+ opp-microvolt-speed4 = <1020000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x1f>;
+ };
+
+ opp-1104000000 {
+ opp-hz = /bits/ 64 <1104000000>;
+ opp-microvolt-speed0 = <1000000>;
+ opp-microvolt-speed2 = <1000000>;
+ opp-microvolt-speed3 = <1000000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x0d>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt-speed0 = <1050000>;
+ opp-microvolt-speed1 = <1020000>;
+ opp-microvolt-speed2 = <1050000>;
+ opp-microvolt-speed3 = <1050000>;
+ opp-microvolt-speed4 = <1100000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x1f>;
+ };
+
+ opp-1320000000 {
+ opp-hz = /bits/ 64 <1320000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x1d>;
+ };
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x0d>;
+ };
+
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt-speed1 = <1100000>;
+ opp-microvolt-speed3 = <1100000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ opp-supported-hw = <0x0a>;
+ };
+ };
+};
+
+&cpu0 {
+ operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu1 {
+ operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu2 {
+ operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu3 {
+ operating-points-v2 = <&cpu_opp_table>;
+};
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -26,6 +26,7 @@
reg = <0>;
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
+ #cooling-cells = <2>;
};
cpu1: cpu@1 {
@@ -34,6 +35,7 @@
reg = <1>;
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
+ #cooling-cells = <2>;
};
cpu2: cpu@2 {
@@ -42,6 +44,7 @@
reg = <2>;
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
+ #cooling-cells = <2>;
};
cpu3: cpu@3 {
@@ -50,6 +53,7 @@
reg = <3>;
enable-method = "psci";
clocks = <&ccu CLK_CPUX>;
+ #cooling-cells = <2>;
};
};
@@ -143,6 +147,10 @@
ths_calibration: thermal-sensor-calibration@14 {
reg = <0x14 0x8>;
};
+
+ cpu_speed_grade: cpu-speed-grade@0 {
+ reg = <0x0 2>;
+ };
};
watchdog: watchdog@30090a0 {

View File

@ -0,0 +1,86 @@
From 09d0aaa0ae9c80ff9569393b206226c1008801b1 Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@arm.com>
Date: Thu, 18 Apr 2024 16:44:08 +0100
Subject: [PATCH] arm64: dts: allwinner: h616: enable DVFS for all boards
With the DT bindings now describing the format of the CPU OPP tables, we
can include the OPP table in each board's .dts file, and specify the CPU
power supply.
This allows to enable DVFS, and get up to 50% of performance benefit in
the highest OPP, or up to 60% power savings in the lowest OPP, compared
to the fixed 1GHz @ 1.0V OPP we are running in by default at the moment.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
.../boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi | 5 +++++
arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts | 5 +++++
arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts | 5 +++++
.../boot/dts/allwinner/sun50i-h618-longan-module-3h.dtsi | 5 +++++
.../arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts | 5 +++++
arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts | 5 +++++
.../boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts | 5 +++++
7 files changed, 35 insertions(+)
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
@@ -6,12 +6,17 @@
/dts-v1/;
#include "sun50i-h616-orangepi-zero.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
/ {
model = "OrangePi Zero2";
compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
};
+&cpu0 {
+ cpu-supply = <&reg_dcdca>;
+};
+
&emac0 {
allwinner,rx-delay-ps = <3100>;
allwinner,tx-delay-ps = <700>;
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
@@ -6,6 +6,7 @@
/dts-v1/;
#include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -32,6 +33,10 @@
};
};
+&cpu0 {
+ cpu-supply = <&reg_dcdca>;
+};
+
&ehci0 {
status = "okay";
};
--- a/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts
@@ -6,12 +6,17 @@
/dts-v1/;
#include "sun50i-h616-orangepi-zero.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
/ {
model = "OrangePi Zero3";
compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h618";
};
+&cpu0 {
+ cpu-supply = <&reg_dcdc2>;
+};
+
&emac0 {
allwinner,tx-delay-ps = <700>;
phy-mode = "rgmii-rxid";

View File

@ -0,0 +1,51 @@
From d2059d3b548409905b20b4f52495bffbd7c8da8b Mon Sep 17 00:00:00 2001
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Mon, 22 Apr 2024 08:58:51 +0530
Subject: [PATCH] cpufreq: sun50i: Fix build warning around snprint()
The Sun50i driver generates a warning with W=1:
warning: '%d' directive output may be truncated writing between 1 and 10 bytes into a region of size 2 [-Wformat-truncation=]
Fix it by allocating a big enough array to print an integer.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202404191715.LDwMm2gP-lkp@intel.com/
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Chen-Yu Tsai <wens@csie.org>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Julian Calaby <julian.calaby@gmail.com>
---
drivers/cpufreq/sun50i-cpufreq-nvmem.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -19,8 +19,6 @@
#include <linux/pm_opp.h>
#include <linux/slab.h>
-#define MAX_NAME_LEN 7
-
#define NVMEM_MASK 0x7
#define NVMEM_SHIFT 5
@@ -208,7 +206,7 @@ static int sun50i_cpufreq_get_efuse(void
static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
{
int *opp_tokens;
- char name[MAX_NAME_LEN];
+ char name[] = "speedXXXXXXXXXXX"; /* Integers can take 11 chars max */
unsigned int cpu, supported_hw;
struct dev_pm_opp_config config = {};
int speed;
@@ -235,7 +233,7 @@ static int sun50i_cpufreq_nvmem_probe(st
config.supported_hw_count = 1;
}
- snprintf(name, MAX_NAME_LEN, "speed%d", speed);
+ snprintf(name, sizeof(name), "speed%d", speed);
config.prop_name = name;
for_each_possible_cpu(cpu) {

View File

@ -0,0 +1,34 @@
From 76a6fc5644b2a1c70868bec24a078f784600ef2a Mon Sep 17 00:00:00 2001
From: Dan Carpenter <dan.carpenter@linaro.org>
Date: Wed, 24 Apr 2024 14:40:11 +0300
Subject: [PATCH] cpufreq: sun50i: fix error returns in dt_has_supported_hw()
The dt_has_supported_hw() function returns type bool. That means these
negative error codes are cast to true but the function should return
false instead.
Fixes: fa5aec9561cf ("cpufreq: sun50i: Add support for opp_supported_hw")
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/sun50i-cpufreq-nvmem.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -136,11 +136,11 @@ static bool dt_has_supported_hw(void)
cpu_dev = get_cpu_device(0);
if (!cpu_dev)
- return -ENODEV;
+ return false;
np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
if (!np)
- return -ENOENT;
+ return false;
for_each_child_of_node(np, opp) {
if (of_find_property(opp, "opp-supported-hw", NULL)) {