mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-24 14:25:56 +00:00
Merge patch series "Add OPP_LOW support for J7200"
Aniket Limaye <a-limaye@ti.com> says: This series adds OPP_LOW spec data in k3_avs driver and enables a config option to select the OPP_LOW performance point. J7200 SOC supports OPP_LOW and OPP_NOM as two Operating Performance Points as per (7.5 Operating Performance Points) section in the Datasheet [0]. - A72SS/MSMC at 2 GHz/1GHz operation must use OPP_NOM. - A72SS/MSMC at 1 GHz/500 MHz operation can use OPP_NOM or OPP_LOW voltage (though OPP_LOW voltage is recommended to reduce power consumption). The actual OPP voltage for the device is read from the efuse and updated in k3_avs_probe(). The default j7200 devicetree and k3_avs driver set OPP_NOM spec frequency and voltage. In the board init file, if K3_OPP_LOW config is enabled, Check if OPP_LOW AVS voltage read from efuse is valid and update frequency (A72 and MSMC) and voltage (VDD_CPU) as per the OPP_LOW spec. [0]: https://www.ti.com/lit/gpn/dra821u (J7200 Datasheet) Test logs: https://gist.github.com/aniket-l/328ad93ed60c2419ed7be9f85e6b6075 - With series applied on master and CONFIG_K3_OPP_LOW enabled in j7200_evm_r5_defconfig - Logs shown with and without efuse register programmed for OPP_0 (Errors out if OPP_0 not found, programs OPP_LOW spec if found) - Voltage update verified using 'i2c md 0x4c 0xe' in u-boot - Frequency update verified using 'k3conf clock dump' in linux Link: https://lore.kernel.org/r/20241119003617.1871183-1-a-limaye@ti.com
This commit is contained in:
commit
fe76d868f7
6 changed files with 143 additions and 6 deletions
|
@ -23,11 +23,12 @@
|
|||
<&k3_pds 202 TI_SCI_PD_EXCLUSIVE>,
|
||||
<&k3_pds 4 TI_SCI_PD_EXCLUSIVE>;
|
||||
resets = <&k3_reset 202 0>;
|
||||
clocks = <&k3_clks 61 1>, <&k3_clks 202 2>;
|
||||
clock-names = "gtc", "core";
|
||||
assigned-clocks = <&k3_clks 202 2>, <&k3_clks 61 1>, <&k3_clks 323 0>;
|
||||
assigned-clock-parents= <0>, <0>, <&k3_clks 323 2>;
|
||||
assigned-clock-rates = <2000000000>, <200000000>;
|
||||
clocks = <&k3_clks 61 1>, <&k3_clks 202 2>, <&k3_clks 4 1> ;
|
||||
clock-names = "gtc", "core", "msmc";
|
||||
assigned-clocks = <&k3_clks 202 2>, <&k3_clks 61 1>, <&k3_clks 4 1>,
|
||||
<&k3_clks 323 0>;
|
||||
assigned-clock-parents= <0>, <0>, <0>, <&k3_clks 323 2>;
|
||||
assigned-clock-rates = <2000000000>, <200000000>, <1000000000>;
|
||||
ti,sci = <&dmsc>;
|
||||
ti,sci-proc-id = <32>;
|
||||
ti,sci-host-id = <10>;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <fdtdec.h>
|
||||
#include <mmc.h>
|
||||
#include <remoteproc.h>
|
||||
#include <k3-avs.h>
|
||||
|
||||
#include "../sysfw-loader.h"
|
||||
#include "../common.h"
|
||||
|
@ -39,6 +40,12 @@
|
|||
#define NB_THREADMAP_BIT0 BIT(0)
|
||||
#define NB_THREADMAP_BIT1 BIT(1)
|
||||
|
||||
/* TISCI DEV ID for A72, MSMC Clock */
|
||||
#define DEV_A72SS0_CORE0_0_ID 202
|
||||
#define DEV_A72SS0_CORE0_0_ARM_CLK_CLK_ID 2
|
||||
#define DEV_A72SS0_CORE0_ID 4
|
||||
#define DEV_A72SS0_CORE0_MSMC_CLK_ID 1
|
||||
|
||||
#ifdef CONFIG_K3_LOAD_SYSFW
|
||||
struct fwl_data cbass_hc_cfg0_fwls[] = {
|
||||
#if defined(CONFIG_TARGET_J721E_R5_EVM)
|
||||
|
@ -147,6 +154,78 @@ static void setup_navss_nb(void)
|
|||
writel(NB_THREADMAP_BIT1, (uintptr_t)NAVSS0_NBSS_NB1_CFG_NB_THREADMAP);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
|
||||
static int get_clock_index_by_dev_id(ofnode node, u32 dev_id, u32 clk_id)
|
||||
{
|
||||
ofnode clknode;
|
||||
int count, i;
|
||||
struct ofnode_phandle_args phandle_args;
|
||||
|
||||
clknode = ofnode_by_compatible(ofnode_null(), "ti,k2g-sci-clk");
|
||||
if (!ofnode_valid(clknode)) {
|
||||
printf("%s: clock-controller not found\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
count = ofnode_count_phandle_with_args(node, "assigned-clocks", "#clock-cells", 0);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (ofnode_parse_phandle_with_args(node, "assigned-clocks",
|
||||
"#clock-cells", 0, i, &phandle_args)) {
|
||||
printf("%s: Could not parse assigned-clocks at index %d\n", __func__, i);
|
||||
continue;
|
||||
}
|
||||
if (ofnode_equal(clknode, phandle_args.node) &&
|
||||
phandle_args.args[0] == dev_id && phandle_args.args[1] == clk_id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int fdt_fixup_a72ss_clock_frequency(void)
|
||||
{
|
||||
int index, size;
|
||||
u32 *rates;
|
||||
ofnode node;
|
||||
|
||||
node = ofnode_by_compatible(ofnode_null(), "ti,am654-rproc");
|
||||
if (!ofnode_valid(node)) {
|
||||
printf("%s: A72 not found\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rates = fdt_getprop_w(ofnode_to_fdt(node), ofnode_to_offset(node),
|
||||
"assigned-clock-rates", &size);
|
||||
if (!rates) {
|
||||
printf("%s: Wrong A72 assigned-clocks-rates configuration\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update A72 Clock Frequency to OPP_LOW spec */
|
||||
index = get_clock_index_by_dev_id(node,
|
||||
DEV_A72SS0_CORE0_0_ID,
|
||||
DEV_A72SS0_CORE0_0_ARM_CLK_CLK_ID);
|
||||
if (index < 0 || index >= (size / sizeof(u32))) {
|
||||
printf("%s: Wrong A72 assigned-clocks configuration\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
rates[index] = cpu_to_fdt32(1000000000);
|
||||
printf("Changed A72 CPU frequency to %dHz in DT\n", 1000000000);
|
||||
|
||||
/* Update MSMC Clock Frequency to OPP_LOW spec */
|
||||
index = get_clock_index_by_dev_id(node,
|
||||
DEV_A72SS0_CORE0_ID,
|
||||
DEV_A72SS0_CORE0_MSMC_CLK_ID);
|
||||
if (index < 0 || index >= (size / sizeof(u32))) {
|
||||
printf("%s: Wrong A72 assigned-clocks configuration\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
rates[index] = cpu_to_fdt32(500000000);
|
||||
printf("Changed MSMC frequency to %dHz in DT\n", 500000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This uninitialized global variable would normal end up in the .bss section,
|
||||
* but the .bss is cleared between writing and reading this variable, so move
|
||||
|
@ -301,8 +380,19 @@ void board_init_f(ulong dummy)
|
|||
#if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(k3_avs),
|
||||
&dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
printf("AVS init failed: %d\n", ret);
|
||||
} else if (IS_ENABLED(CONFIG_K3_OPP_LOW)) {
|
||||
ret = k3_avs_check_opp(dev, J721E_VDD_MPU, AM6_OPP_LOW);
|
||||
if (ret) {
|
||||
printf("OPP_LOW: k3_avs_check_opp failed: %d\n", ret);
|
||||
} else {
|
||||
ret = fdt_fixup_a72ss_clock_frequency();
|
||||
if (ret)
|
||||
printf("OPP_LOW: fdt_fixup_a72ss_clock_frequency failed: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_K3_J721E_DDRSS)
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
config K3_LOAD_SYSFW
|
||||
bool
|
||||
|
||||
config K3_OPP_LOW
|
||||
depends on ARCH_K3 && K3_AVS0
|
||||
bool "Enable OPP_LOW on supported TI K3 SoCs"
|
||||
help
|
||||
Enabling this will allow Socs with the proper efuse to run at a lower
|
||||
MPU core voltage and adjust frequency according to SoC TRM
|
||||
|
||||
config K3_QOS
|
||||
bool "Enable Quality of Service (QoS) Settings for TI K3 SoCs"
|
||||
default y if SOC_K3_AM62A7
|
||||
|
|
|
@ -102,6 +102,7 @@ CONFIG_K3_SEC_PROXY=y
|
|||
CONFIG_FS_LOADER=y
|
||||
CONFIG_SPL_FS_LOADER=y
|
||||
CONFIG_K3_AVS0=y
|
||||
# CONFIG_K3_OPP_LOW is not set
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_SPL_MMC_HS400_SUPPORT=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
|
|
|
@ -121,6 +121,11 @@ static int k3_avs_program_voltage(struct k3_avs_privdata *priv,
|
|||
if (!vd->supply)
|
||||
return -ENODEV;
|
||||
|
||||
if (!volt) {
|
||||
dev_err(priv->dev, "No efuse found for opp_%d\n", opp_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vd->opp = opp_id;
|
||||
vd->flags |= VD_FLAG_INIT_DONE;
|
||||
|
||||
|
@ -192,6 +197,33 @@ static int match_opp(struct vd_data *vd, u32 freq)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* k3_check_opp: Check for presence of opp efuse
|
||||
* @dev: AVS device
|
||||
* @vdd_id: voltage domain ID
|
||||
* @opp_id: opp id to check if voltage is present
|
||||
*
|
||||
* Checks to see if an opp has voltage. k3_avs probe will populate
|
||||
* voltage data if efuse is present. Returns 0 if data is valid.
|
||||
*/
|
||||
int k3_avs_check_opp(struct udevice *dev, int vdd_id, int opp_id)
|
||||
{
|
||||
struct k3_avs_privdata *priv = dev_get_priv(dev);
|
||||
struct vd_data *vd;
|
||||
int volt;
|
||||
|
||||
vd = get_vd(priv, vdd_id);
|
||||
if (!vd)
|
||||
return -EINVAL;
|
||||
|
||||
volt = vd->opps[opp_id].volt;
|
||||
if (volt)
|
||||
return 0;
|
||||
|
||||
printf("No efuse found for opp_%d\n", opp_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* k3_avs_notify_freq: Notify clock rate change towards AVS subsystem
|
||||
* @dev_id: Device ID for the clock to be changed
|
||||
|
@ -501,6 +533,10 @@ static struct vd_data j721e_vd_data[] = {
|
|||
.dev_id = 202, /* J721E_DEV_A72SS0_CORE0 */
|
||||
.clk_id = 2, /* ARM clock */
|
||||
.opps = {
|
||||
[AM6_OPP_LOW] = {
|
||||
.volt = 0, /* voltage TBD after OPP fuse reading */
|
||||
.freq = 1000000000,
|
||||
},
|
||||
[AM6_OPP_NOM] = {
|
||||
.volt = 880000, /* TBD in DM */
|
||||
.freq = 2000000000,
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
|
||||
#define NUM_OPPS 4
|
||||
|
||||
#define AM6_OPP_LOW 0
|
||||
#define AM6_OPP_NOM 1
|
||||
#define AM6_OPP_OD 2
|
||||
#define AM6_OPP_TURBO 3
|
||||
|
||||
int k3_avs_set_opp(struct udevice *dev, int vdd_id, int opp_id);
|
||||
int k3_avs_notify_freq(int dev_id, int clk_id, u32 freq);
|
||||
int k3_avs_check_opp(struct udevice *dev, int vdd_id, int opp_id);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue