diff options
Diffstat (limited to 'drivers/firmware')
| -rw-r--r-- | drivers/firmware/firmware-zynqmp.c | 36 | ||||
| -rw-r--r-- | drivers/firmware/scmi/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/firmware/scmi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/firmware/scmi/sandbox-scmi_agent.c | 4 | ||||
| -rw-r--r-- | drivers/firmware/scmi/scmi_agent-uclass.c | 40 | ||||
| -rw-r--r-- | drivers/firmware/scmi/smt.c | 14 | ||||
| -rw-r--r-- | drivers/firmware/scmi/vendors/imx/Kconfig | 15 | ||||
| -rw-r--r-- | drivers/firmware/scmi/vendors/imx/Makefile | 8 | ||||
| -rw-r--r-- | drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c | 179 | ||||
| -rw-r--r-- | drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c | 213 | ||||
| -rw-r--r-- | drivers/firmware/ti_sci.c | 12 |
11 files changed, 496 insertions, 34 deletions
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index e07ec3929b2..3742467caee 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -3,6 +3,7 @@ * Xilinx Zynq MPSoC Firmware driver * * Copyright (C) 2018-2019 Xilinx, Inc. + * Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc. */ #include <asm/arch/hardware.h> @@ -158,7 +159,7 @@ unsigned int zynqmp_firmware_version(void) if (pm_api_version == ZYNQMP_PM_VERSION_INVALID) { ret = xilinx_pm_request(PM_GET_API_VERSION, 0, 0, 0, 0, - ret_payload); + 0, 0, ret_payload); if (ret) panic("PMUFW is not found - Please load it!\n"); @@ -202,7 +203,7 @@ int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value int ret; ret = xilinx_pm_request(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG, - config, value, NULL); + config, value, 0, 0, NULL); if (ret) printf("%s: node %d: set_gem_config %d failed\n", __func__, node, config); @@ -215,7 +216,7 @@ int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) int ret; ret = xilinx_pm_request(PM_IOCTL, node, IOCTL_SET_SD_CONFIG, - config, value, NULL); + config, value, 0, 0, NULL); if (ret) printf("%s: node %d: set_sd_config %d failed\n", __func__, node, config); @@ -236,7 +237,7 @@ u32 zynqmp_pm_get_bootmode_reg(void) } ret = xilinx_pm_request(PM_IOCTL, CRP_BOOT_MODE_REG_NODE, IOCTL_READ_REG, - CRP_BOOT_MODE_REG_OFFSET, 0, ret_payload); + CRP_BOOT_MODE_REG_OFFSET, 0, 0, 0, ret_payload); if (ret) { printf("%s: node 0x%x: get_bootmode 0x%x failed\n", __func__, CRP_BOOT_MODE_REG_NODE, CRP_BOOT_MODE_REG_OFFSET); @@ -259,7 +260,8 @@ u32 zynqmp_pm_get_pmc_multi_boot_reg(void) } ret = xilinx_pm_request(PM_IOCTL, PM_REG_PMC_GLOBAL_NODE, IOCTL_READ_REG, - PMC_MULTI_BOOT_MODE_REG_OFFSET, 0, ret_payload); + PMC_MULTI_BOOT_MODE_REG_OFFSET, 0, 0, 0, + ret_payload); if (ret) { printf("%s: node 0x%x: get_bootmode 0x%x failed\n", __func__, PM_REG_PMC_GLOBAL_NODE, PMC_MULTI_BOOT_MODE_REG_OFFSET); @@ -276,7 +278,7 @@ int zynqmp_pm_feature(const u32 api_id) /* Check feature check API version */ ret = xilinx_pm_request(PM_FEATURE_CHECK, api_id, 0, 0, 0, - ret_payload); + 0, 0, ret_payload); if (ret) return ret; @@ -296,7 +298,7 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) /* Check feature check API version */ ret = xilinx_pm_request(PM_FEATURE_CHECK, PM_FEATURE_CHECK, 0, 0, 0, - ret_payload); + 0, 0, ret_payload); if (ret) return ret; @@ -308,7 +310,7 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) */ ret = xilinx_pm_request(PM_FEATURE_CHECK, api_id, 0, 0, 0, - ret_payload); + 0, 0, ret_payload); if (ret) return ret; @@ -340,7 +342,7 @@ int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) flush_dcache_range((ulong)cfg_obj, (ulong)(cfg_obj + size)); err = xilinx_pm_request(PM_SET_CONFIGURATION, (u32)(u64)cfg_obj, 0, 0, - 0, ret_payload); + 0, 0, 0, ret_payload); if (err == XST_PM_NO_ACCESS) { return -EACCES; } @@ -425,13 +427,14 @@ U_BOOT_DRIVER(zynqmp_power) = { smc_call_handler_t __data smc_call_handler; static int smc_call_legacy(u32 api_id, u32 arg0, u32 arg1, u32 arg2, - u32 arg3, u32 *ret_payload) + u32 arg3, u32 arg4, u32 arg5, u32 *ret_payload) { struct pt_regs regs; regs.regs[0] = PM_SIP_SVC | api_id; regs.regs[1] = ((u64)arg1 << 32) | arg0; regs.regs[2] = ((u64)arg3 << 32) | arg2; + regs.regs[3] = arg4; smc_call(®s); @@ -441,16 +444,18 @@ static int smc_call_legacy(u32 api_id, u32 arg0, u32 arg1, u32 arg2, ret_payload[2] = (u32)regs.regs[1]; ret_payload[3] = upper_32_bits(regs.regs[1]); ret_payload[4] = (u32)regs.regs[2]; + ret_payload[5] = upper_32_bits((u32)regs.regs[2]); + ret_payload[6] = (u32)regs.regs[3]; } return (ret_payload) ? ret_payload[0] : 0; } int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, - u32 arg3, u32 *ret_payload) + u32 arg3, u32 arg4, u32 arg5, u32 *ret_payload) { - debug("%s at EL%d, API ID: 0x%0x, 0x%0x, 0x%0x, 0x%0x, 0x%0x\n", - __func__, current_el(), api_id, arg0, arg1, arg2, arg3); + debug("%s at EL%d, API ID: 0x%0x, 0x%0x, 0x%0x, 0x%0x, 0x%0x, 0x%0x, 0x%0x\n", + __func__, current_el(), api_id, arg0, arg1, arg2, arg3, arg4, arg5); if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) { #if defined(CONFIG_ZYNQMP_IPI) @@ -459,7 +464,7 @@ int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, * is capable to handle PMUFW_PAYLOAD_ARG_CNT bytes but the * firmware API is limited by the SMC call size */ - u32 regs[] = {api_id, arg0, arg1, arg2, arg3}; + u32 regs[] = {api_id, arg0, arg1, arg2, arg3, arg4, arg5}; int ret; if (api_id == PM_FPGA_LOAD) { @@ -481,7 +486,8 @@ int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, #endif } - return smc_call_handler(api_id, arg0, arg1, arg2, arg3, ret_payload); + return smc_call_handler(api_id, arg0, arg1, arg2, arg3, arg4, + arg5, ret_payload); } static const struct udevice_id zynqmp_firmware_ids[] = { diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index 8cf85f0d7a1..33e089c460b 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -41,3 +41,11 @@ config SCMI_AGENT_OPTEE help Enable the SCMI communication channel based on OP-TEE transport for compatible "linaro,scmi-optee". + +config SCMI_ID_VENDOR_80 + bool + +config SCMI_ID_VENDOR_82 + bool + +source "drivers/firmware/scmi/vendors/imx/Kconfig" diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index dae42863589..6129726f817 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SCMI_AGENT_OPTEE) += optee_agent.o obj-$(CONFIG_SCMI_POWER_DOMAIN) += pwdom.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o +obj-y += vendors/imx/ diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 74a87832dcb..5b242a039c2 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -828,7 +828,7 @@ static int sandbox_scmi_clock_rate_get(struct udevice *dev, static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) { - struct scmi_clk_state_in *in = NULL; + struct scmi_clk_state_in_v1 *in = NULL; struct scmi_clk_state_out *out = NULL; struct sandbox_scmi_clk *clk_state = NULL; @@ -836,7 +836,7 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) !msg->out_msg || msg->out_msg_sz < sizeof(*out)) return -EINVAL; - in = (struct scmi_clk_state_in *)msg->in_msg; + in = (struct scmi_clk_state_in_v1 *)msg->in_msg; out = (struct scmi_clk_state_out *)msg->out_msg; clk_state = get_scmi_clk_state(in->clock_id); diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 69a277e8786..ad825d66da2 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -86,21 +86,41 @@ struct udevice *scmi_get_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_BASE: proto = priv->base_dev; break; +#if IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN) case SCMI_PROTOCOL_ID_POWER_DOMAIN: proto = priv->pwdom_dev; break; +#endif +#if IS_ENABLED(CONFIG_CLK_SCMI) case SCMI_PROTOCOL_ID_CLOCK: proto = priv->clock_dev; break; +#endif +#if IS_ENABLED(CONFIG_RESET_SCMI) case SCMI_PROTOCOL_ID_RESET_DOMAIN: proto = priv->resetdom_dev; break; +#endif +#if IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: proto = priv->voltagedom_dev; break; +#endif +#if IS_ENABLED(CONFIG_PINCTRL_IMX_SCMI) case SCMI_PROTOCOL_ID_PINCTRL: proto = priv->pinctrl_dev; break; +#endif +#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_80) + case SCMI_PROTOCOL_ID_VENDOR_80: + proto = priv->vendor_dev_80; + break; +#endif +#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82) + case SCMI_PROTOCOL_ID_VENDOR_82: + proto = priv->vendor_dev_82; + break; +#endif default: dev_err(dev, "Protocol not supported\n"); proto = NULL; @@ -139,21 +159,41 @@ static int scmi_add_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_BASE: priv->base_dev = proto; break; +#if IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN) case SCMI_PROTOCOL_ID_POWER_DOMAIN: priv->pwdom_dev = proto; break; +#endif +#if IS_ENABLED(CONFIG_CLK_SCMI) case SCMI_PROTOCOL_ID_CLOCK: priv->clock_dev = proto; break; +#endif +#if IS_ENABLED(CONFIG_RESET_SCMI) case SCMI_PROTOCOL_ID_RESET_DOMAIN: priv->resetdom_dev = proto; break; +#endif +#if IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: priv->voltagedom_dev = proto; break; +#endif +#if IS_ENABLED(CONFIG_PINCTRL_IMX_SCMI) case SCMI_PROTOCOL_ID_PINCTRL: priv->pinctrl_dev = proto; break; +#endif +#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_80) + case SCMI_PROTOCOL_ID_VENDOR_80: + priv->vendor_dev_80 = proto; + break; +#endif +#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82) + case SCMI_PROTOCOL_ID_VENDOR_82: + priv->vendor_dev_82 = proto; + break; +#endif default: dev_err(dev, "Protocol not supported\n"); return -EPROTO; diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c index 237871559f0..cd1c0801f72 100644 --- a/drivers/firmware/scmi/smt.c +++ b/drivers/firmware/scmi/smt.c @@ -61,20 +61,6 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt) if (device_is_compatible(dev, "arm,scmi") && ofnode_has_property(dev_ofnode(dev), "mboxes")) scmi_smt_enable_intr(smt, true); -#ifdef CONFIG_ARM - if (dcache_status()) { - u32 align_size; - - if (IS_ENABLED(CONFIG_ARM64)) - align_size = PAGE_SIZE; - else - align_size = MMU_SECTION_SIZE; - - mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, align_size), - ALIGN(smt->size, align_size), DCACHE_OFF); - } -#endif - return 0; } diff --git a/drivers/firmware/scmi/vendors/imx/Kconfig b/drivers/firmware/scmi/vendors/imx/Kconfig new file mode 100644 index 00000000000..16850502bbb --- /dev/null +++ b/drivers/firmware/scmi/vendors/imx/Kconfig @@ -0,0 +1,15 @@ +config IMX_SM_CPU + bool "Enable i.MX System Manager CPU API" + depends on ARCH_IMX9 && SCMI_FIRMWARE + select SCMI_ID_VENDOR_82 + help + If you say Y here to enable i.MX System Manager CPU + API to work on some NXP i.MX processors. + +config IMX_SM_LMM + bool "Enable i.MX System Manager Logical Machine API" + depends on ARCH_IMX9 && SCMI_FIRMWARE + select SCMI_ID_VENDOR_80 + help + If you say Y here to enable i.MX System Manager Logical Machine + API to work on some NXP i.MX processors. diff --git a/drivers/firmware/scmi/vendors/imx/Makefile b/drivers/firmware/scmi/vendors/imx/Makefile new file mode 100644 index 00000000000..59ff8640dc1 --- /dev/null +++ b/drivers/firmware/scmi/vendors/imx/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2025 NXP +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_IMX_SM_CPU) += imx-sm-cpu.o +obj-$(CONFIG_IMX_SM_LMM) += imx-sm-lmm.o diff --git a/drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c b/drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c new file mode 100644 index 00000000000..28dfac642ec --- /dev/null +++ b/drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * i.MX SCMI CPU protocol + * + * Copyright 2025 NXP + */ + +#include <compiler.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <misc.h> +#include <scmi_agent.h> +#include <scmi_agent-uclass.h> +#include <scmi_protocols.h> +#include <scmi_nxp_protocols.h> + +enum scmi_imx_cpu_protocol_cmd { + SCMI_IMX_CPU_ATTRIBUTES = 0x3, + SCMI_IMX_CPU_START = 0x4, + SCMI_IMX_CPU_STOP = 0x5, + SCMI_IMX_CPU_RESET_VECTOR_SET = 0x6, + SCMI_IMX_CPU_INFO_GET = 0xC, +}; + +struct scmi_imx_cpu_priv { + u32 nr_cpu; +}; + +struct scmi_imx_cpu_reset_vector_set_in { + __le32 cpuid; +#define CPU_VEC_FLAGS_RESUME BIT(31) +#define CPU_VEC_FLAGS_START BIT(30) +#define CPU_VEC_FLAGS_BOOT BIT(29) + __le32 flags; + __le32 resetvectorlow; + __le32 resetvectorhigh; +}; + +struct scmi_imx_cpu_info_get_out { + __le32 status; +#define CPU_RUN_MODE_START 0 +#define CPU_RUN_MODE_HOLD 1 +#define CPU_RUN_MODE_STOP 2 +#define CPU_RUN_MODE_SLEEP 3 + __le32 runmode; + __le32 sleepmode; + __le32 resetvectorlow; + __le32 resetvectorhigh; +}; + +int scmi_imx_cpu_start(struct udevice *dev, u32 cpuid, bool start) +{ + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_82, + .message_id = SCMI_IMX_CPU_STOP, + .in_msg = (u8 *)&cpuid, + .in_msg_sz = sizeof(cpuid), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + if (start) + msg.message_id = SCMI_IMX_CPU_START; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_imx_cpu_reset_vector_set(struct udevice *dev, u32 cpuid, u32 flags, u64 vector, + bool start, bool boot, bool resume) +{ + struct scmi_imx_cpu_reset_vector_set_in in; + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_82, + .message_id = SCMI_IMX_CPU_RESET_VECTOR_SET, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.cpuid = cpu_to_le32(cpuid); + in.flags = cpu_to_le32(0); + if (start) + in.flags |= CPU_VEC_FLAGS_START; + if (boot) + in.flags |= CPU_VEC_FLAGS_BOOT; + if (resume) + in.flags |= CPU_VEC_FLAGS_RESUME; + in.resetvectorlow = cpu_to_le32(lower_32_bits(vector)); + in.resetvectorhigh = cpu_to_le32(upper_32_bits(vector)); + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_imx_cpu_started(struct udevice *dev, u32 cpuid, bool *started) +{ + struct scmi_imx_cpu_info_get_out out; + u32 mode; + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_82, + .message_id = SCMI_IMX_CPU_INFO_GET, + .in_msg = (u8 *)&cpuid, + .in_msg_sz = sizeof(cpuid), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + status = cpu_to_le32(out.status); + if (status) + return scmi_to_linux_errno(status); + + mode = le32_to_cpu(out.runmode); + if (mode == CPU_RUN_MODE_START || mode == CPU_RUN_MODE_SLEEP) + *started = true; + + return 0; +} + +static int scmi_imx_cpu_probe(struct udevice *dev) +{ + int ret; + + ret = devm_scmi_of_get_channel(dev); + if (ret) { + dev_err(dev, "failed to get channel (%d)\n", ret); + return ret; + } + + return 0; +} + +U_BOOT_DRIVER(scmi_imx_cpu) = { + .name = "scmi_imx_cpu", + .id = UCLASS_SCMI_BASE, + .probe = scmi_imx_cpu_probe, + .priv_auto = sizeof(struct scmi_imx_cpu_priv), +}; + +static struct scmi_proto_match match[] = { + { .proto_id = SCMI_PROTOCOL_ID_VENDOR_82}, + { /* Sentinel */ } +}; + +U_BOOT_SCMI_PROTO_DRIVER(scmi_imx_cpu, match); diff --git a/drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c b/drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c new file mode 100644 index 00000000000..2fd791ca853 --- /dev/null +++ b/drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * i.MX SCMI LMM protocol + * + * Copyright 2025 NXP + */ + +#include <compiler.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <linux/types.h> +#include <misc.h> +#include <scmi_agent.h> +#include <scmi_agent-uclass.h> +#include <scmi_protocols.h> +#include <scmi_nxp_protocols.h> + +enum scmi_imx_lmm_protocol_cmd { + SCMI_IMX_LMM_ATTRIBUTES = 0x3, + SCMI_IMX_LMM_BOOT = 0x4, + SCMI_IMX_LMM_RESET = 0x5, + SCMI_IMX_LMM_SHUTDOWN = 0x6, + SCMI_IMX_LMM_WAKE = 0x7, + SCMI_IMX_LMM_SUSPEND = 0x8, + SCMI_IMX_LMM_NOTIFY = 0x9, + SCMI_IMX_LMM_RESET_REASON = 0xA, + SCMI_IMX_LMM_POWER_ON = 0xB, + SCMI_IMX_LMM_RESET_VECTOR_SET = 0xC, +}; + +struct scmi_imx_lmm_priv { + u32 nr_lmm; +}; + +struct scmi_msg_imx_lmm_attributes_out { + __le32 status; + __le32 lmid; + __le32 attributes; + __le32 state; + __le32 errstatus; + u8 name[LMM_MAX_NAME]; +}; + +struct scmi_imx_lmm_reset_vector_set_in { + __le32 lmid; + __le32 cpuid; + __le32 flags; /* reserved for future extension */ + __le32 resetvectorlow; + __le32 resetvectorhigh; +}; + +struct scmi_imx_lmm_shutdown_in { + __le32 lmid; +#define SCMI_IMX_LMM_SHUTDOWN_GRACEFUL BIT(0) + __le32 flags; +}; + +int scmi_imx_lmm_info(struct udevice *dev, u32 lmid, struct scmi_imx_lmm_info *info) +{ + struct scmi_msg_imx_lmm_attributes_out out; + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80, + .message_id = SCMI_IMX_LMM_ATTRIBUTES, + .in_msg = (u8 *)&lmid, + .in_msg_sz = sizeof(lmid), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + status = cpu_to_le32(out.status); + if (status) + return scmi_to_linux_errno(status); + + info->lmid = le32_to_cpu(out.lmid); + info->state = le32_to_cpu(out.state); + info->errstatus = le32_to_cpu(out.errstatus); + strcpy(info->name, out.name); + dev_dbg(dev, "i.MX LMM: Logical Machine(%d), name: %s\n", + info->lmid, info->name); + + return ret; +} + +int scmi_imx_lmm_power_boot(struct udevice *dev, u32 lmid, bool boot) +{ + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80, + .message_id = SCMI_IMX_LMM_POWER_ON, + .in_msg = (u8 *)&lmid, + .in_msg_sz = sizeof(lmid), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + if (boot) + msg.message_id = SCMI_IMX_LMM_BOOT; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_imx_lmm_reset_vector_set(struct udevice *dev, u32 lmid, u32 cpuid, u32 flags, u64 vector) +{ + struct scmi_imx_lmm_reset_vector_set_in in; + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80, + .message_id = SCMI_IMX_LMM_RESET_VECTOR_SET, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.lmid = lmid; + in.cpuid = cpuid; + in.flags = flags; + in.resetvectorlow = vector & 0xFFFFFFFF; + in.resetvectorhigh = vector >> 32; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_imx_lmm_shutdown(struct udevice *dev, u32 lmid, bool flags) +{ + struct scmi_imx_lmm_shutdown_in in; + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80, + .message_id = SCMI_IMX_LMM_SHUTDOWN, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.lmid = lmid; + if (flags & SCMI_IMX_LMM_SHUTDOWN_GRACEFUL) + in.flags = cpu_to_le32(SCMI_IMX_LMM_SHUTDOWN_GRACEFUL); + else + in.flags = cpu_to_le32(0); + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +static int scmi_imx_lmm_probe(struct udevice *dev) +{ + int ret; + + ret = devm_scmi_of_get_channel(dev); + if (ret) { + dev_err(dev, "failed to get channel (%d)\n", ret); + return ret; + } + + return 0; +} + +U_BOOT_DRIVER(scmi_imx_lmm) = { + .name = "scmi_imx_lmm", + .id = UCLASS_SCMI_BASE, + .probe = scmi_imx_lmm_probe, + .priv_auto = sizeof(struct scmi_imx_lmm_priv), +}; + +static struct scmi_proto_match match[] = { + { .proto_id = SCMI_PROTOCOL_ID_VENDOR_80}, + { /* Sentinel */ } +}; + +U_BOOT_SCMI_PROTO_DRIVER(scmi_imx_lmm, match); diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 8013afef304..6f57dcfe8de 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -191,9 +191,9 @@ static int ti_sci_get_response(struct ti_sci_info *info, /* Sanity check for message response */ if (hdr->seq != info->seq) { - dev_dbg(info->dev, "%s: Message for %d is not expected\n", + dev_err(info->dev, "%s: Message for %d is not expected\n", __func__, hdr->seq); - return ret; + return -EINVAL; } if (msg->len > info->desc->max_msg_size) { @@ -1365,6 +1365,8 @@ static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle, if (ret) return ret; + resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf; + *parent_id = resp->parent_id; return ret; @@ -3083,7 +3085,10 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, dev_err(dev, "%s resource type ids not available\n", of_prop); return ERR_PTR(sets); } - temp = malloc(sets); + temp = devm_kmalloc(dev, sets, GFP_KERNEL); + if (!temp) + return ERR_PTR(-ENOMEM); + sets /= sizeof(u32); res->sets = sets; @@ -3123,6 +3128,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, return ERR_PTR(-ENOMEM); } + devm_kfree(dev, temp); if (valid_set) return res; |
