14c4212e9SVincent Guittot // SPDX-License-Identifier: BSD-2-Clause
24c4212e9SVincent Guittot /*
34c4212e9SVincent Guittot * Copyright (c) 2019-2022, Linaro Limited
4*ce6ea411SValentin Caron * Copyright (c) 2025, STMicroelectronics
54c4212e9SVincent Guittot */
64c4212e9SVincent Guittot
74c4212e9SVincent Guittot #include <arch_main.h>
84c4212e9SVincent Guittot #include <config.h>
94c4212e9SVincent Guittot #include <initcall.h>
104c4212e9SVincent Guittot #include <kernel/panic.h>
114c4212e9SVincent Guittot #include <mm/core_memprot.h>
124c4212e9SVincent Guittot #include <optee_scmi.h>
13*ce6ea411SValentin Caron #include <scmi_agent_configuration.h>
144c4212e9SVincent Guittot #include <scmi/scmi_server.h>
154c4212e9SVincent Guittot
164c4212e9SVincent Guittot /*
174c4212e9SVincent Guittot * OP-TEE helper function exported to SCP-firmware
184c4212e9SVincent Guittot */
smt_phys_to_virt(uintptr_t pa,size_t sz,bool shmem_is_secure)194c4212e9SVincent Guittot uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure)
204c4212e9SVincent Guittot {
214c4212e9SVincent Guittot if (shmem_is_secure)
224c4212e9SVincent Guittot return (uintptr_t)phys_to_virt(pa, MEM_AREA_IO_SEC, sz);
234c4212e9SVincent Guittot else
244c4212e9SVincent Guittot return (uintptr_t)phys_to_virt(pa, MEM_AREA_IO_NSEC, sz);
254c4212e9SVincent Guittot }
264c4212e9SVincent Guittot
274c4212e9SVincent Guittot /*
284c4212e9SVincent Guittot * SCMI server APIs exported to OP-TEE core
294c4212e9SVincent Guittot */
scmi_server_get_channels_count(void)304c4212e9SVincent Guittot int scmi_server_get_channels_count(void)
314c4212e9SVincent Guittot {
324c4212e9SVincent Guittot return scmi_get_devices_count();
334c4212e9SVincent Guittot }
344c4212e9SVincent Guittot
scmi_server_get_channel(unsigned int channel_id,int * handle)354c4212e9SVincent Guittot TEE_Result scmi_server_get_channel(unsigned int channel_id, int *handle)
364c4212e9SVincent Guittot {
374c4212e9SVincent Guittot int fwk_id = 0;
384c4212e9SVincent Guittot
394c4212e9SVincent Guittot fwk_id = scmi_get_device(channel_id);
404c4212e9SVincent Guittot if (fwk_id < 0)
414c4212e9SVincent Guittot return TEE_ERROR_BAD_PARAMETERS;
424c4212e9SVincent Guittot
434c4212e9SVincent Guittot if (handle)
444c4212e9SVincent Guittot *handle = fwk_id;
454c4212e9SVincent Guittot
464c4212e9SVincent Guittot return TEE_SUCCESS;
474c4212e9SVincent Guittot }
484c4212e9SVincent Guittot
scmi_server_smt_process_thread(unsigned int channel_id)494c4212e9SVincent Guittot TEE_Result scmi_server_smt_process_thread(unsigned int channel_id)
504c4212e9SVincent Guittot {
514c4212e9SVincent Guittot TEE_Result res = TEE_ERROR_GENERIC;
524c4212e9SVincent Guittot int fwk_id = 0;
534c4212e9SVincent Guittot
544c4212e9SVincent Guittot res = scmi_server_get_channel(channel_id, &fwk_id);
554c4212e9SVincent Guittot if (!res)
564c4212e9SVincent Guittot scmi_process_mbx_smt(fwk_id);
574c4212e9SVincent Guittot
584c4212e9SVincent Guittot return res;
594c4212e9SVincent Guittot }
604c4212e9SVincent Guittot
scmi_server_msg_process_thread(unsigned int channel_id,void * in_buf,size_t in_sz,void * out_buf,size_t * out_sz)614c4212e9SVincent Guittot TEE_Result scmi_server_msg_process_thread(unsigned int channel_id,
624c4212e9SVincent Guittot void *in_buf, size_t in_sz,
634c4212e9SVincent Guittot void *out_buf, size_t *out_sz)
644c4212e9SVincent Guittot {
654c4212e9SVincent Guittot TEE_Result res = TEE_ERROR_GENERIC;
664c4212e9SVincent Guittot int fwk_id = 0;
674c4212e9SVincent Guittot
684c4212e9SVincent Guittot res = scmi_server_get_channel(channel_id, &fwk_id);
694c4212e9SVincent Guittot if (!res)
704c4212e9SVincent Guittot scmi_process_mbx_msg(fwk_id, in_buf, in_sz, out_buf, out_sz);
714c4212e9SVincent Guittot
724c4212e9SVincent Guittot return res;
734c4212e9SVincent Guittot }
744c4212e9SVincent Guittot
scmi_server_initialize(void)754c4212e9SVincent Guittot static TEE_Result scmi_server_initialize(void)
764c4212e9SVincent Guittot {
774c4212e9SVincent Guittot int rc = 0;
784c4212e9SVincent Guittot
79*ce6ea411SValentin Caron if (IS_ENABLED(CFG_SCMI_SCPFW_FROM_DT)) {
80*ce6ea411SValentin Caron struct scpfw_config *cfg = scmi_scpfw_get_configuration();
81*ce6ea411SValentin Caron
82*ce6ea411SValentin Caron assert(cfg);
83*ce6ea411SValentin Caron rc = scmi_configure(cfg);
84*ce6ea411SValentin Caron if (rc < 0) {
85*ce6ea411SValentin Caron EMSG("SCMI server configuration failed: %d", rc);
86*ce6ea411SValentin Caron panic();
87*ce6ea411SValentin Caron }
88*ce6ea411SValentin Caron scmi_scpfw_release_configuration();
89*ce6ea411SValentin Caron }
90*ce6ea411SValentin Caron
914c4212e9SVincent Guittot rc = scmi_arch_init();
924c4212e9SVincent Guittot if (rc < 0) {
934c4212e9SVincent Guittot EMSG("SCMI server init failed: %d", rc);
944c4212e9SVincent Guittot panic();
954c4212e9SVincent Guittot }
964c4212e9SVincent Guittot
974c4212e9SVincent Guittot return TEE_SUCCESS;
984c4212e9SVincent Guittot }
994c4212e9SVincent Guittot
1004c4212e9SVincent Guittot boot_final(scmi_server_initialize);
101