[U-Boot] [PATCH 1/4] imx8: scu_api: add sc_pm_get_resource_power_mode

Add sc_pm_get_resource_power_mode to get resource power mode
Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/include/asm/arch-imx8/sci/sci.h | 2 ++ drivers/misc/imx8/scu_api.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+)
diff --git a/arch/arm/include/asm/arch-imx8/sci/sci.h b/arch/arm/include/asm/arch-imx8/sci/sci.h index 97377697f0..b73cda2286 100644 --- a/arch/arm/include/asm/arch-imx8/sci/sci.h +++ b/arch/arm/include/asm/arch-imx8/sci/sci.h @@ -58,6 +58,8 @@ static inline int sc_err_to_linux(sc_err_t err) /* PM API*/ int sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_power_mode_t mode); +int sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t *mode); int sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, sc_pm_clock_rate_t *rate); int sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c index d9c4d5d784..b181c6a29f 100644 --- a/drivers/misc/imx8/scu_api.c +++ b/drivers/misc/imx8/scu_api.c @@ -119,6 +119,31 @@ int sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, return ret; }
+int sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t *mode) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_PM); + RPC_FUNC(&msg) = (u8)(PM_FUNC_GET_RESOURCE_POWER_MODE); + RPC_U16(&msg, 0U) = (u16)(resource); + RPC_SIZE(&msg) = 2U; + + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + printf("%s: resource:%d: res:%d\n", + __func__, resource, RPC_R8(&msg)); + + if (mode) + *mode = RPC_U8(&msg, 0U); + + return ret; +} + /* PAD */ int sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, u32 val) {

Add sc_pm_cpu_start to start M4 and DSP core.
Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/include/asm/arch-imx8/sci/sci.h | 3 +++ drivers/misc/imx8/scu_api.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+)
diff --git a/arch/arm/include/asm/arch-imx8/sci/sci.h b/arch/arm/include/asm/arch-imx8/sci/sci.h index b73cda2286..e7ed92f76e 100644 --- a/arch/arm/include/asm/arch-imx8/sci/sci.h +++ b/arch/arm/include/asm/arch-imx8/sci/sci.h @@ -83,4 +83,7 @@ sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource);
/* PAD API */ int sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, u32 val); + +int sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, + sc_faddr_t address); #endif diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c index b181c6a29f..756ba449ab 100644 --- a/drivers/misc/imx8/scu_api.c +++ b/drivers/misc/imx8/scu_api.c @@ -13,6 +13,8 @@
DECLARE_GLOBAL_DATA_PTR;
+#define B2U8(X) (((X) != SC_FALSE) ? (u8)(0x01U) : (u8)(0x00U)) + /* CLK and PM */ int sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_clk_t clk, sc_pm_clock_rate_t *rate) @@ -390,3 +392,31 @@ sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource)
return !!result; } + +int sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, + sc_faddr_t address) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + if (!dev) + hang(); + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_PM); + RPC_FUNC(&msg) = (u8)(PM_FUNC_CPU_START); + RPC_U32(&msg, 0U) = (u32)(address >> 32ULL); + RPC_U32(&msg, 4U) = (u32)(address); + RPC_U16(&msg, 8U) = (u16)(resource); + RPC_U8(&msg, 10U) = B2U8(enable); + RPC_SIZE(&msg) = 4U; + + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + printf("%s: resource:%d address:0x%llx: res:%d\n", + __func__, resource, address, RPC_R8(&msg)); + + return ret; +}

Make i.MX8M able to use bootaux command.
Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index d3942f6b3f..d086230e9b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -23,7 +23,7 @@ config IMX_RDC
config IMX_BOOTAUX bool "Support boot auxiliary core" - depends on ARCH_MX7 || ARCH_MX6 || ARCH_VF610 + depends on ARCH_IMX8M || ARCH_MX7 || ARCH_MX6 || ARCH_VF610 help bootaux [addr] to boot auxiliary core.

Add bootaux to kick M4 and DSP. When M4 is not kicked by ROM/SCU, we could use U-Boot to kick as i.MX6/7.
Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/Kconfig | 2 +- arch/arm/mach-imx/imx8/Makefile | 1 + arch/arm/mach-imx/imx8/bootaux.c | 225 +++++++++++++++++++++++++++++++++++++++ arch/arm/mach-imx/imx_bootaux.c | 2 + 4 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-imx/imx8/bootaux.c
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index d086230e9b..39f388ef93 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -23,7 +23,7 @@ config IMX_RDC
config IMX_BOOTAUX bool "Support boot auxiliary core" - depends on ARCH_IMX8M || ARCH_MX7 || ARCH_MX6 || ARCH_VF610 + depends on ARCH_IMX8M || ARCH_IMX8 || ARCH_MX7 || ARCH_MX6 || ARCH_VF610 help bootaux [addr] to boot auxiliary core.
diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile index 31ad169ccf..d8b0c2a7b9 100644 --- a/arch/arm/mach-imx/imx8/Makefile +++ b/arch/arm/mach-imx/imx8/Makefile @@ -5,3 +5,4 @@ #
obj-y += cpu.o iomux.o +obj-$(CONFIG_IMX_BOOTAUX) += bootaux.o diff --git a/arch/arm/mach-imx/imx8/bootaux.c b/arch/arm/mach-imx/imx8/bootaux.c new file mode 100644 index 0000000000..3bbe679120 --- /dev/null +++ b/arch/arm/mach-imx/imx8/bootaux.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 NXP + */ + +#include <common.h> +#include <elf.h> +#include <errno.h> +#include <power-domain.h> + +#include <asm/arch/sci/sci.h> +#include <asm/arch/sys_proto.h> + +#ifdef CONFIG_IMX8QM +int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) +{ + sc_rsrc_t core_rsrc, mu_rsrc; + sc_faddr_t tcml_addr; + u32 tcm_size = SZ_256K; /* TCML + TCMU */ + ulong addr; + + switch (core_id) { + case 0: + core_rsrc = SC_R_M4_0_PID0; + tcml_addr = 0x34FE0000; + mu_rsrc = SC_R_M4_0_MU_1A; + break; + case 1: + core_rsrc = SC_R_M4_1_PID0; + tcml_addr = 0x38FE0000; + mu_rsrc = SC_R_M4_1_MU_1A; + break; + default: + printf("Not support this core boot up, ID:%u\n", core_id); + return -EINVAL; + } + + addr = (sc_faddr_t)boot_private_data; + + if (addr >= tcml_addr && addr <= tcml_addr + tcm_size) { + printf("Wrong image address 0x%lx, should not in TCML\n", + addr); + return -EINVAL; + } + + printf("Power on M4 and MU\n"); + + if (sc_pm_set_resource_power_mode(-1, core_rsrc, + SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + + if (sc_pm_set_resource_power_mode(-1, mu_rsrc, + SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + + printf("Copy M4 image from 0x%lx to TCML 0x%lx\n", + addr, (ulong)tcml_addr); + + if (addr != tcml_addr) + memcpy((void *)tcml_addr, (void *)addr, tcm_size); + + printf("Start M4 %u\n", core_id); + if (sc_pm_cpu_start(-1, core_rsrc, true, tcml_addr) != SC_ERR_NONE) + return -EIO; + + printf("bootaux complete\n"); + return 0; +} +#endif + +#ifdef CONFIG_IMX8QXP +static unsigned long load_elf_image_shdr(unsigned long addr) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + Elf32_Shdr *shdr; /* Section header structure pointer */ + unsigned char *strtab = 0; /* String table pointer */ + unsigned char *image; /* Binary image pointer */ + int i; /* Loop counter */ + + ehdr = (Elf32_Ehdr *)addr; + + /* Find the section header string table for output info */ + shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + + (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); + + if (shdr->sh_type == SHT_STRTAB) + strtab = (unsigned char *)(addr + shdr->sh_offset); + + /* Load each appropriate section */ + for (i = 0; i < ehdr->e_shnum; ++i) { + shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + + (i * sizeof(Elf32_Shdr))); + + if (!(shdr->sh_flags & SHF_ALLOC) || + shdr->sh_addr == 0 || shdr->sh_size == 0) { + continue; + } + + if (strtab) { + debug("%sing %s @ 0x%08lx (%ld bytes)\n", + (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", + &strtab[shdr->sh_name], + (unsigned long)shdr->sh_addr, + (long)shdr->sh_size); + } + + if (shdr->sh_type == SHT_NOBITS) { + memset((void *)(uintptr_t)shdr->sh_addr, 0, + shdr->sh_size); + } else { + image = (unsigned char *)addr + shdr->sh_offset; + memcpy((void *)(uintptr_t)shdr->sh_addr, + (const void *)image, shdr->sh_size); + } + flush_cache(shdr->sh_addr, shdr->sh_size); + } + + return ehdr->e_entry; +} + +int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) +{ + struct power_domain pd; + sc_rsrc_t core_rsrc, mu_rsrc = -1; + sc_faddr_t aux_core_ram; + u32 size; + ulong addr; + + switch (core_id) { + case 0: + core_rsrc = SC_R_M4_0_PID0; + aux_core_ram = 0x34FE0000; + mu_rsrc = SC_R_M4_0_MU_1A; + size = SZ_256K; + break; + case 1: + core_rsrc = SC_R_DSP; + aux_core_ram = 0x596f8000; + size = SZ_2K; + break; + default: + printf("Not support this core boot up, ID:%u\n", core_id); + return -EINVAL; + } + + addr = (sc_faddr_t)boot_private_data; + + if (addr >= aux_core_ram && addr <= aux_core_ram + size) { + printf("Wrong image address 0x%lx, should not in aux core ram\n", + addr); + return -EINVAL; + } + + printf("Power on aux core %d\n", core_id); + + if (sc_pm_set_resource_power_mode(-1, core_rsrc, + SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + + if (mu_rsrc != -1) { + if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) + return -EIO; + } + + if (core_id == 1) { + if (sc_pm_clock_enable(-1, core_rsrc, SC_PM_CLK_PER, + true, false) != SC_ERR_NONE) { + printf("Error enable clock\n"); + return -EIO; + } + + /* TODO : add power domain support */ + + return -EIO: + } + + printf("Copy image from 0x%lx to 0x%lx\n", addr, (ulong)aux_core_ram); + if (core_id == 0) { + /* M4 use bin file */ + memcpy((void *)aux_core_ram, (void *)addr, size); + } else { + /* HIFI use elf file */ + if (!valid_elf_image(addr)) + return -1; + addr = load_elf_image_shdr(addr); + } + + printf("Start %s\n", core_id == 0 ? "M4" : "HIFI"); + + if (sc_pm_cpu_start(-1, core_rsrc, true, aux_core_ram) != SC_ERR_NONE) + return -EIO; + + printf("bootaux complete\n"); + return 0; +} +#endif + +int arch_auxiliary_core_check_up(u32 core_id) +{ + sc_rsrc_t core_rsrc; + sc_pm_power_mode_t power_mode; + + switch (core_id) { + case 0: + core_rsrc = SC_R_M4_0_PID0; + break; +#ifdef CONFIG_IMX8QM + case 1: + core_rsrc = SC_R_M4_1_PID0; + break; +#endif + default: + printf("Not support this core, ID:%u\n", core_id); + return 0; + } + + if (sc_pm_get_resource_power_mode(-1, core_rsrc, + &power_mode) != SC_ERR_NONE) + return 0; + + if (power_mode != SC_PM_PW_MODE_OFF) + return 1; + + return 0; +} diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c index 18d7e6819c..267bc08ca4 100644 --- a/arch/arm/mach-imx/imx_bootaux.c +++ b/arch/arm/mach-imx/imx_bootaux.c @@ -10,6 +10,7 @@ #include <imx_sip.h> #include <linux/compiler.h>
+#ifndef CONFIG_IMX8 int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) { ulong stack, pc; @@ -50,6 +51,7 @@ int arch_auxiliary_core_check_up(u32 core_id) return 1; #endif } +#endif
/* * To i.MX6SX and i.MX7D, the image supported by bootaux needs
participants (1)
-
Peng Fan