[PATCH v1 0/4] board: verdin-am62: set cpu core voltage depending on speed grade

The series moves the existing access functions to the AM62 Device Identification fields and adds function for the not yet accessible fields to be available to all.
This is then used in the Verdin AM62 board code to set the CPU core voltage according to speed grade to gain more than 100mW power consumption reduction for the slower speed graded SKUs.
Max Krummenacher (4): board: verdin-am62: improve comment on usb phy core voltage arm: mach-k3: am62: move device identification accessor functions to header arm: mach-k3: am62: provide more soc feature info accessors board: verdin-am62: set cpu core voltage depending on speed grade
arch/arm/mach-k3/am625_fdt.c | 23 -------- arch/arm/mach-k3/include/mach/am62_hardware.h | 39 ++++++++++++++ board/toradex/verdin-am62/verdin-am62.c | 52 ++++++++++++++++++- 3 files changed, 89 insertions(+), 25 deletions(-)

From: Max Krummenacher max.krummenacher@toradex.com
TI recommends to clear the bit independent of the used voltage. So the comment which claims to do it due to the core voltage at 0.85V is bogus.
See https://e2e.ti.com/support/processors-group/processors/f/processors-forum/12...
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com ---
board/toradex/verdin-am62/verdin-am62.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index d09dda5bccc..4e912b5f32f 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -101,12 +101,13 @@ void spl_board_init(void) { u32 val;
- /* Set USB0 PHY core voltage to 0.85V */ + /* Clear USB0_PHY_CTRL_CORE_VOLTAGE */ + /* TI recommends to clear the bit independent of VDDA_CORE_USB */ val = readl(CTRLMMR_USB0_PHY_CTRL); val &= ~(CORE_VOLTAGE); writel(val, CTRLMMR_USB0_PHY_CTRL);
- /* Set USB1 PHY core voltage to 0.85V */ + /* Clear USB1_PHY_CTRL_CORE_VOLTAGE */ val = readl(CTRLMMR_USB1_PHY_CTRL); val &= ~(CORE_VOLTAGE); writel(val, CTRLMMR_USB1_PHY_CTRL);

On Wed, Jan 17, 2024 at 11:16:46AM +0100, Max Krummenacher wrote:
From: Max Krummenacher max.krummenacher@toradex.com
TI recommends to clear the bit independent of the used voltage. So the comment which claims to do it due to the core voltage at 0.85V is bogus.
See https://e2e.ti.com/support/processors-group/processors/f/processors-forum/12...
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com
For the series, applied to u-boot/master, thanks!

From: Max Krummenacher max.krummenacher@toradex.com
mach-k3/am625_fdt.c does fdt fixup depending on fields in the device identification register. Move the accessors to the device identification register as inline functions into the am62_hardware.h header, so that they can be used for other functionality.
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com ---
arch/arm/mach-k3/am625_fdt.c | 23 ------------------- arch/arm/mach-k3/include/mach/am62_hardware.h | 23 +++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-k3/am625_fdt.c b/arch/arm/mach-k3/am625_fdt.c index 37806907af1..970dd3447de 100644 --- a/arch/arm/mach-k3/am625_fdt.c +++ b/arch/arm/mach-k3/am625_fdt.c @@ -38,29 +38,6 @@ static void fdt_fixup_pru_node_am625(void *blob, int has_pru) fdt_del_node_path(blob, "/bus@f0000/pruss@30040000"); }
-static int k3_get_core_nr(void) -{ - u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); - - return (full_devid & JTAG_DEV_CORE_NR_MASK) >> JTAG_DEV_CORE_NR_SHIFT; -} - -static int k3_has_pru(void) -{ - u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); - u32 feature_mask = (full_devid & JTAG_DEV_FEATURES_MASK) >> - JTAG_DEV_FEATURES_SHIFT; - - return !(feature_mask & JTAG_DEV_FEATURE_NO_PRU); -} - -static int k3_has_gpu(void) -{ - u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); - - return (full_devid & JTAG_DEV_GPU_MASK) >> JTAG_DEV_GPU_SHIFT; -} - int ft_system_setup(void *blob, struct bd_info *bd) { fdt_fixup_cores_nodes_am625(blob, k3_get_core_nr()); diff --git a/arch/arm/mach-k3/include/mach/am62_hardware.h b/arch/arm/mach-k3/include/mach/am62_hardware.h index acd2d109c2c..ea5bcf5d3de 100644 --- a/arch/arm/mach-k3/include/mach/am62_hardware.h +++ b/arch/arm/mach-k3/include/mach/am62_hardware.h @@ -79,6 +79,29 @@
#define TI_SRAM_SCRATCH_BOARD_EEPROM_START 0x43c30000
+static inline int k3_get_core_nr(void) +{ + u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); + + return (full_devid & JTAG_DEV_CORE_NR_MASK) >> JTAG_DEV_CORE_NR_SHIFT; +} + +static inline int k3_has_pru(void) +{ + u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); + u32 feature_mask = (full_devid & JTAG_DEV_FEATURES_MASK) >> + JTAG_DEV_FEATURES_SHIFT; + + return !(feature_mask & JTAG_DEV_FEATURE_NO_PRU); +} + +static inline int k3_has_gpu(void) +{ + u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); + + return (full_devid & JTAG_DEV_GPU_MASK) >> JTAG_DEV_GPU_SHIFT; +} + #if defined(CONFIG_SYS_K3_SPL_ATF) && !defined(__ASSEMBLY__)
static const u32 put_device_ids[] = {};

From: Max Krummenacher max.krummenacher@toradex.com
Add two functions, one which returns the SoC speed grade and one which returns the SoC operating temperature range.
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com ---
arch/arm/mach-k3/include/mach/am62_hardware.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/arch/arm/mach-k3/include/mach/am62_hardware.h b/arch/arm/mach-k3/include/mach/am62_hardware.h index ea5bcf5d3de..54380f36e16 100644 --- a/arch/arm/mach-k3/include/mach/am62_hardware.h +++ b/arch/arm/mach-k3/include/mach/am62_hardware.h @@ -86,6 +86,22 @@ static inline int k3_get_core_nr(void) return (full_devid & JTAG_DEV_CORE_NR_MASK) >> JTAG_DEV_CORE_NR_SHIFT; }
+static inline char k3_get_speed_grade(void) +{ + u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); + u32 speed_grade = (full_devid & JTAG_DEV_SPEED_MASK) >> + JTAG_DEV_SPEED_SHIFT; + + return 'A' - 1 + speed_grade; +} + +static inline int k3_get_temp_grade(void) +{ + u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); + + return (full_devid & JTAG_DEV_TEMP_MASK) >> JTAG_DEV_TEMP_SHIFT; +} + static inline int k3_has_pru(void) { u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID);

From: Max Krummenacher max.krummenacher@toradex.com
Speed grade T requires the VDD_CORE voltage to be 0.85V if using the maximum core frequency.
Speed grades G, K, S allow the VDD_CORE voltage to be 0.75V up to the maximum core frequency but allow to run at 0.85V.
For efficiency in manufacturing and code maintenance we use 0.85V for the PMIC defaults and device tree settings and dynamically adjust the voltage in the PMIC and device tree to 0.75V for lower speed SKU to gain more than 100mW power consumption reduction.
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com ---
board/toradex/verdin-am62/verdin-am62.c | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index 4e912b5f32f..8b9db224069 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -13,10 +13,13 @@ #include <fdt_support.h> #include <init.h> #include <k3-ddrss.h> +#include <power/regulator.h> #include <spl.h>
#include "../common/tdx-cfg-block.h"
+#define VDD_CORE_REG "buck1" + DECLARE_GLOBAL_DATA_PTR;
int board_init(void) @@ -49,9 +52,37 @@ int board_fit_config_name_match(const char *name) } #endif
+static u32 get_vdd_core_nominal(void) +{ + int core_uvolt; + + switch (k3_get_speed_grade()) { + case 'G': + case 'K': + case 'S': + core_uvolt = 750000; + break; + case 'T': + default: + core_uvolt = 850000; + break; + } + return core_uvolt; +} + #if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, struct bd_info *bd) { + int core_uvolt; + + core_uvolt = get_vdd_core_nominal(); + if (core_uvolt != 850000) { + do_fixup_by_path_u32(blob, "/bus@f0000/i2c@20000000/pmic@30/regulators/buck1", + "regulator-max-microvolt", core_uvolt, 0); + do_fixup_by_path_u32(blob, "/bus@f0000/i2c@20000000/pmic@30/regulators/buck1", + "regulator-min-microvolt", core_uvolt, 0); + } + return ft_common_board_setup(blob, bd); } #endif @@ -86,6 +117,22 @@ static void select_dt_from_module_version(void)
int board_late_init(void) { + int ret; + int core_uvolt; + struct udevice *dev = NULL; + + core_uvolt = get_vdd_core_nominal(); + if (core_uvolt != 850000) { + /* Set CPU core voltage to 0.75V for slower speed grades */ + ret = regulator_get_by_devname(VDD_CORE_REG, &dev); + if (ret) + pr_err("VDD CORE Regulator get error: %d\n", ret); + + ret = regulator_set_value_force(dev, core_uvolt); + if (ret) + pr_err("VDD CORE Regulator value setting error: %d\n", ret); + } + select_dt_from_module_version();
return 0;

On Wed, Jan 17, 2024 at 11:16:49AM +0100, Max Krummenacher wrote:
From: Max Krummenacher max.krummenacher@toradex.com
Speed grade T requires the VDD_CORE voltage to be 0.85V if using the maximum core frequency.
Speed grades G, K, S allow the VDD_CORE voltage to be 0.75V up to the maximum core frequency but allow to run at 0.85V.
For efficiency in manufacturing and code maintenance we use 0.85V for the PMIC defaults and device tree settings and dynamically adjust the voltage in the PMIC and device tree to 0.75V for lower speed SKU to gain more than 100mW power consumption reduction.
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com
board/toradex/verdin-am62/verdin-am62.c | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index 4e912b5f32f..8b9db224069 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -13,10 +13,13 @@ #include <fdt_support.h> #include <init.h> #include <k3-ddrss.h> +#include <power/regulator.h>
In the !DM_REGULATOR case regulator.h assumes errno.h to be already included. This happens when compiling the R5 SPL.
Will fix this in a v2 of the series.
Max
#include <spl.h>
#include "../common/tdx-cfg-block.h"
+#define VDD_CORE_REG "buck1"
DECLARE_GLOBAL_DATA_PTR;
int board_init(void) @@ -49,9 +52,37 @@ int board_fit_config_name_match(const char *name) } #endif
+static u32 get_vdd_core_nominal(void) +{
- int core_uvolt;
- switch (k3_get_speed_grade()) {
- case 'G':
- case 'K':
- case 'S':
core_uvolt = 750000;
break;
- case 'T':
- default:
core_uvolt = 850000;
break;
- }
- return core_uvolt;
+}
#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, struct bd_info *bd) {
- int core_uvolt;
- core_uvolt = get_vdd_core_nominal();
- if (core_uvolt != 850000) {
do_fixup_by_path_u32(blob, "/bus@f0000/i2c@20000000/pmic@30/regulators/buck1",
"regulator-max-microvolt", core_uvolt, 0);
do_fixup_by_path_u32(blob, "/bus@f0000/i2c@20000000/pmic@30/regulators/buck1",
"regulator-min-microvolt", core_uvolt, 0);
- }
- return ft_common_board_setup(blob, bd);
} #endif @@ -86,6 +117,22 @@ static void select_dt_from_module_version(void)
int board_late_init(void) {
int ret;
int core_uvolt;
struct udevice *dev = NULL;
core_uvolt = get_vdd_core_nominal();
if (core_uvolt != 850000) {
/* Set CPU core voltage to 0.75V for slower speed grades */
ret = regulator_get_by_devname(VDD_CORE_REG, &dev);
if (ret)
pr_err("VDD CORE Regulator get error: %d\n", ret);
ret = regulator_set_value_force(dev, core_uvolt);
if (ret)
pr_err("VDD CORE Regulator value setting error: %d\n", ret);
}
select_dt_from_module_version();
return 0;
-- 2.42.0

On Thu, Jan 18, 2024 at 10:50:07AM +0100, Max Krummenacher wrote:
On Wed, Jan 17, 2024 at 11:16:49AM +0100, Max Krummenacher wrote:
From: Max Krummenacher max.krummenacher@toradex.com
Speed grade T requires the VDD_CORE voltage to be 0.85V if using the maximum core frequency.
Speed grades G, K, S allow the VDD_CORE voltage to be 0.75V up to the maximum core frequency but allow to run at 0.85V.
For efficiency in manufacturing and code maintenance we use 0.85V for the PMIC defaults and device tree settings and dynamically adjust the voltage in the PMIC and device tree to 0.75V for lower speed SKU to gain more than 100mW power consumption reduction.
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com
board/toradex/verdin-am62/verdin-am62.c | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index 4e912b5f32f..8b9db224069 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -13,10 +13,13 @@ #include <fdt_support.h> #include <init.h> #include <k3-ddrss.h> +#include <power/regulator.h>
In the !DM_REGULATOR case regulator.h assumes errno.h to be already included. This happens when compiling the R5 SPL.
Will fix this in a v2 of the series.
Actually we can go on with the series. While it is true that errno.h is not included in regulator.h, the required header is included and its definitions available.
I will create a separate patch which cleans up the headers, so that they become self contained.
Max
Max
#include <spl.h>
#include "../common/tdx-cfg-block.h"
+#define VDD_CORE_REG "buck1"
DECLARE_GLOBAL_DATA_PTR;
int board_init(void) @@ -49,9 +52,37 @@ int board_fit_config_name_match(const char *name) } #endif
+static u32 get_vdd_core_nominal(void) +{
- int core_uvolt;
- switch (k3_get_speed_grade()) {
- case 'G':
- case 'K':
- case 'S':
core_uvolt = 750000;
break;
- case 'T':
- default:
core_uvolt = 850000;
break;
- }
- return core_uvolt;
+}
#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, struct bd_info *bd) {
- int core_uvolt;
- core_uvolt = get_vdd_core_nominal();
- if (core_uvolt != 850000) {
do_fixup_by_path_u32(blob, "/bus@f0000/i2c@20000000/pmic@30/regulators/buck1",
"regulator-max-microvolt", core_uvolt, 0);
do_fixup_by_path_u32(blob, "/bus@f0000/i2c@20000000/pmic@30/regulators/buck1",
"regulator-min-microvolt", core_uvolt, 0);
- }
- return ft_common_board_setup(blob, bd);
} #endif @@ -86,6 +117,22 @@ static void select_dt_from_module_version(void)
int board_late_init(void) {
int ret;
int core_uvolt;
struct udevice *dev = NULL;
core_uvolt = get_vdd_core_nominal();
if (core_uvolt != 850000) {
/* Set CPU core voltage to 0.75V for slower speed grades */
ret = regulator_get_by_devname(VDD_CORE_REG, &dev);
if (ret)
pr_err("VDD CORE Regulator get error: %d\n", ret);
ret = regulator_set_value_force(dev, core_uvolt);
if (ret)
pr_err("VDD CORE Regulator value setting error: %d\n", ret);
}
select_dt_from_module_version();
return 0;
-- 2.42.0

On Thu, Jan 18, 2024 at 05:31:20PM +0100, Max Krummenacher wrote:
On Thu, Jan 18, 2024 at 10:50:07AM +0100, Max Krummenacher wrote:
On Wed, Jan 17, 2024 at 11:16:49AM +0100, Max Krummenacher wrote:
From: Max Krummenacher max.krummenacher@toradex.com
Speed grade T requires the VDD_CORE voltage to be 0.85V if using the maximum core frequency.
Speed grades G, K, S allow the VDD_CORE voltage to be 0.75V up to the maximum core frequency but allow to run at 0.85V.
For efficiency in manufacturing and code maintenance we use 0.85V for the PMIC defaults and device tree settings and dynamically adjust the voltage in the PMIC and device tree to 0.75V for lower speed SKU to gain more than 100mW power consumption reduction.
Signed-off-by: Max Krummenacher max.krummenacher@toradex.com
board/toradex/verdin-am62/verdin-am62.c | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index 4e912b5f32f..8b9db224069 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -13,10 +13,13 @@ #include <fdt_support.h> #include <init.h> #include <k3-ddrss.h> +#include <power/regulator.h>
In the !DM_REGULATOR case regulator.h assumes errno.h to be already included. This happens when compiling the R5 SPL.
Will fix this in a v2 of the series.
Actually we can go on with the series. While it is true that errno.h is not included in regulator.h, the required header is included and its definitions available.
I will create a separate patch which cleans up the headers, so that they become self contained.
FTR, https://lore.kernel.org/all/20240118181106.4133924-1-max.oss.09@gmail.com/
As Max wrote this series does not require that cleanup.
Francesco

On Wed, Jan 17, 2024 at 11:16:45AM +0100, Max Krummenacher wrote:
The series moves the existing access functions to the AM62 Device Identification fields and adds function for the not yet accessible fields to be available to all.
This is then used in the Verdin AM62 board code to set the CPU core voltage according to speed grade to gain more than 100mW power consumption reduction for the slower speed graded SKUs.
For the whole series,
Reviewed-by: Francesco Dolcini francesco.dolcini@toradex.com
participants (3)
-
Francesco Dolcini
-
Max Krummenacher
-
Tom Rini